diff --git a/libs/deer/src/impls/core.rs b/libs/deer/src/impls/core.rs index 0beaefd36f0..34d839e1ec1 100644 --- a/libs/deer/src/impls/core.rs +++ b/libs/deer/src/impls/core.rs @@ -4,6 +4,7 @@ mod bool; mod cmp; mod floating; mod integral; +mod marker; mod mem; mod non_zero; mod option; diff --git a/libs/deer/src/impls/core/marker.rs b/libs/deer/src/impls/core/marker.rs new file mode 100644 index 00000000000..ebd68f9f72b --- /dev/null +++ b/libs/deer/src/impls/core/marker.rs @@ -0,0 +1,45 @@ +use core::marker::PhantomData; + +use error_stack::{Result, ResultExt}; + +use crate::{ + error::{DeserializeError, VisitorError}, + Deserialize, Deserializer, Document, Reflection, Schema, Visitor, +}; + +struct PhantomDataVisitor(PhantomData); + +impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor { + type Value = PhantomData; + + fn expecting(&self) -> Document { + Self::Value::reflection() + } + + fn visit_none(self) -> Result { + Ok(PhantomData) + } + + fn visit_null(self) -> Result { + Ok(PhantomData) + } +} + +pub struct PhantomDataReflection; + +impl Reflection for PhantomDataReflection { + fn schema(_: &mut Document) -> Schema { + // TODO: this is also optional (none) + // currently we're unable to express that constraint (something for 0.2) + Schema::new("null") + } +} + +impl<'de, T: ?Sized> Deserialize<'de> for PhantomData { + type Reflection = PhantomDataReflection; + + fn deserialize>(de: D) -> Result { + de.deserialize_null(PhantomDataVisitor(Self)) + .change_context(DeserializeError) + } +} diff --git a/libs/deer/tests/test_impls_core_marker.rs b/libs/deer/tests/test_impls_core_marker.rs new file mode 100644 index 00000000000..fb1c8076c1e --- /dev/null +++ b/libs/deer/tests/test_impls_core_marker.rs @@ -0,0 +1,8 @@ +use core::marker::PhantomData; + +use deer_desert::{assert_tokens, Token}; + +#[test] +fn phantom_data_ok() { + assert_tokens::>(&PhantomData, &[Token::Null]); +}