diff --git a/implementations/rust/src/lib.rs b/implementations/rust/src/lib.rs index 310802a..c9f70cc 100644 --- a/implementations/rust/src/lib.rs +++ b/implementations/rust/src/lib.rs @@ -29,7 +29,7 @@ mod dom { } } - fn as_preserves>(&self) -> Result { + fn as_preserves, D: Domain>(&self) -> Result { Ok(Value::symbol(&format!("Dom::{:?}", self)).wrap()) } } diff --git a/implementations/rust/src/ser.rs b/implementations/rust/src/ser.rs index f4b4889..580fe86 100644 --- a/implementations/rust/src/ser.rs +++ b/implementations/rust/src/ser.rs @@ -144,22 +144,18 @@ impl<'a, 'b, W: Writer, N: NestedValue, D: Domain> serde::Serializer for &'a fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> where T: Serialize { - if name == crate::value::value::MAGIC_VALUE { - let b = unsafe { Box::from_raw(*((value as *const T) as *const u64) as *mut &Value) }; - let v: &Value = *b; - Encoder::new(self.write, self.placeholders).write_value(v)?; - Ok(()) - } else if name == crate::value::value::MAGIC_NESTEDVALUE { - let b = unsafe { Box::from_raw(*((value as *const T) as *const u64) as *mut &N) }; - let v: &N = *b; - Encoder::new(self.write, self.placeholders).write(v)?; - Ok(()) - } else { - // TODO: This is apparently discouraged, and we should apparently just serialize `value`? - self.write.open_record(1)?; - self.write_symbol(name)?; - value.serialize(&mut *self)?; - Ok(self.write.close_record()?) + match super::value::magic::receive_output_value(name, value) { + Some(v) => { + Encoder::new(self.write, self.placeholders).write(&v.copy_via(&|_| unreachable!()))?; + Ok(()) + } + None => { + // TODO: This is apparently discouraged, and we should apparently just serialize `value`? + self.write.open_record(1)?; + self.write_symbol(name)?; + value.serialize(&mut *self)?; + Ok(self.write.close_record()?) + } } } diff --git a/implementations/rust/src/value/de.rs b/implementations/rust/src/value/de.rs index d695184..f5706bc 100644 --- a/implementations/rust/src/value/de.rs +++ b/implementations/rust/src/value/de.rs @@ -251,17 +251,14 @@ impl<'de, 'a, N: NestedValue, D: 'de + Domain> serde::de::Deserializer<'de> fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor<'de> { - if name == crate::value::value::MAGIC_VALUE { - let v: Box> = Box::new(self.input.clone().value_owned()); - visitor.visit_u64(Box::into_raw(v) as u64) - } else if name == crate::value::value::MAGIC_NESTEDVALUE { - let v: Box = Box::new(self.input.clone()); - visitor.visit_u64(Box::into_raw(v) as u64) - } else { - let fs = self.check(|v| v.as_simple_record(name, Some(1)), - ExpectedKind::SimpleRecord(name, Some(1)))?; - self.input = &fs[0]; - visitor.visit_newtype_struct(self) + match super::magic::transmit_input_value(name, || self.input.copy_to_null_domain()) { + Some(v) => visitor.visit_u64(v), + None => { + let fs = self.check(|v| v.as_simple_record(name, Some(1)), + ExpectedKind::SimpleRecord(name, Some(1)))?; + self.input = &fs[0]; + visitor.visit_newtype_struct(self) + } } } diff --git a/implementations/rust/src/value/magic.rs b/implementations/rust/src/value/magic.rs new file mode 100644 index 0000000..dbca66b --- /dev/null +++ b/implementations/rust/src/value/magic.rs @@ -0,0 +1,65 @@ +use super::{ + NullDomain, + value::{ + ArcValue, + NestedValue, + Domain, + }, +}; + +pub static MAGIC: &str = "$____Preserves_Serde_Magic"; + +pub type IOValue = ArcValue; + +struct IOValueVisitor; +impl<'de> serde::de::Visitor<'de> for IOValueVisitor { + type Value = IOValue; + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "a magic encoding of an embedded Preserves Value") + } + fn visit_u64(self, v: u64) -> Result where E: serde::de::Error { + let b = unsafe { Box::from_raw(v as *mut IOValue) }; + Ok(*b) + } +} + +pub fn output_value(serializer: S, v: IOValue) -> + Result +{ + serializer.serialize_newtype_struct(MAGIC, &(Box::into_raw(Box::new(v)) as u64)) +} + +pub fn input_value<'de, D: serde::Deserializer<'de>>(deserializer: D) -> + Result +{ + deserializer.deserialize_newtype_struct(MAGIC, IOValueVisitor) +} + +pub fn input_value_via<'de, D: serde::Deserializer<'de>, N: NestedValue, Dom: Domain>(deserializer: D) -> + Result +{ + Ok(input_value(deserializer)?.copy_via(&|_| unreachable!())) +} + +//--------------------------------------------------------------------------- + +pub fn receive_output_value(name: &'static str, magic_value: &T) -> Option { + if name == MAGIC { + let b = unsafe { Box::from_raw(*((magic_value as *const T) as *const u64) as *mut IOValue) }; + let v: IOValue = *b; + Some(v) + } else { + None + } +} + +pub fn transmit_input_value(name: &'static str, f: F) -> Option +where F: FnOnce() -> IOValue +{ + if name == MAGIC { + let b: Box = Box::new(f()); + Some(Box::into_raw(b) as u64) + } else { + None + } +} diff --git a/implementations/rust/src/value/mod.rs b/implementations/rust/src/value/mod.rs index c3f6d0a..f810831 100644 --- a/implementations/rust/src/value/mod.rs +++ b/implementations/rust/src/value/mod.rs @@ -8,6 +8,8 @@ pub mod ser; pub mod value; pub mod writer; +pub mod magic; + pub use codec::Codec; pub use de::Deserializer; pub use de::from_value; diff --git a/implementations/rust/src/value/ser.rs b/implementations/rust/src/value/ser.rs index f459319..1834ab9 100644 --- a/implementations/rust/src/value/ser.rs +++ b/implementations/rust/src/value/ser.rs @@ -134,17 +134,12 @@ impl, D: Domain> serde::Serializer for Serializer { fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result where T: Serialize { - if name == crate::value::value::MAGIC_VALUE { - let b = unsafe { Box::from_raw(*((value as *const T) as *const u64) as *mut &Value) }; - let v: &Value = *b; - Ok(v.clone().wrap()) - } else if name == crate::value::value::MAGIC_NESTEDVALUE { - let b = unsafe { Box::from_raw(*((value as *const T) as *const u64) as *mut &N) }; - let v: &N = *b; - Ok(v.clone()) - } else { - // TODO: This is apparently discouraged, and we should apparently just serialize `value`? - Ok(Value::simple_record(name, vec![to_value(value)]).wrap()) + match super::magic::receive_output_value(name, value) { + Some(v) => Ok(v.copy_via(&|_| unreachable!())), + None => { + // TODO: This is apparently discouraged, and we should apparently just serialize `value`? + Ok(Value::simple_record(name, vec![to_value(value)]).wrap()) + } } } diff --git a/implementations/rust/src/value/value.rs b/implementations/rust/src/value/value.rs index bf76ce5..9b208ac 100644 --- a/implementations/rust/src/value/value.rs +++ b/implementations/rust/src/value/value.rs @@ -19,7 +19,7 @@ pub trait Domain: Sized + Debug + Clone + Eq + Hash + Ord { enc.write(&self.as_preserves()?) } - fn as_preserves>(&self) -> Result { + fn as_preserves, D: Domain>(&self) -> Result { Err(std::io::Error::new(std::io::ErrorKind::InvalidData, format!("Cannot Preserves-encode domain-specific value {:?}", self))) @@ -54,9 +54,13 @@ pub trait NestedValue: Sized + Debug + Clone + Eq + Hash + Ord { self.value().copy_via(f)) } - fn copy_via_id,>(&self) -> M { + fn copy_via_id>(&self) -> M { self.copy_via(&|d| Value::Domain(d.clone())) } + + fn copy_to_null_domain>(&self) -> M { + self.copy_via(&|d| d.as_preserves::().unwrap().value_owned()) + } } /// The `Value`s from the specification. @@ -533,6 +537,10 @@ impl, D: Domain> Value { Value::Domain(d) => f(d), } } + + pub fn copy_to_null_domain>(&self) -> Value { + self.copy_via(&|d| d.as_preserves::().unwrap().value_owned()) + } } impl, D: Domain> Index for Value { @@ -560,45 +568,28 @@ impl, D: Domain> Index<&N> for Value { //--------------------------------------------------------------------------- // This part is a terrible hack -pub static MAGIC_VALUE: &str = "$____Preserves_Value"; -pub static MAGIC_NESTEDVALUE: &str = "$____Preserves_NestedValue"; - impl, D: Domain> serde::Serialize for Value { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_newtype_struct(MAGIC_VALUE, &(Box::into_raw(Box::new(self)) as u64)) - } -} - -struct CastVisitor(std::marker::PhantomData); -impl<'de, T> serde::de::Visitor<'de> for CastVisitor { - type Value = T; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "a magic encoding of an embedded value") - } - fn visit_u64(self, v: u64) -> Result where E: serde::de::Error { - let b = unsafe { Box::from_raw(v as *mut T) }; - Ok(*b) + super::magic::output_value(serializer, self.copy_to_null_domain().wrap()) } } impl<'de, N: NestedValue, Dom: Domain> serde::Deserialize<'de> for Value { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { - deserializer.deserialize_newtype_struct( - MAGIC_VALUE, CastVisitor::>(std::marker::PhantomData)) + Ok(super::magic::input_value_via::<'de, D, N, Dom>(deserializer)?.value_owned()) } } pub fn serialize_nested_value(v: &N, serializer: S) -> Result where S: serde::Serializer, N: NestedValue + serde::Serialize { - serializer.serialize_newtype_struct(MAGIC_NESTEDVALUE, &(Box::into_raw(Box::new(v)) as u64)) + super::magic::output_value(serializer, v.copy_to_null_domain()) } pub fn deserialize_nested_value<'de, D, N, Dom: Domain>(deserializer: D) -> Result where D: serde::Deserializer<'de>, N: NestedValue + serde::Deserialize<'de> { - deserializer.deserialize_newtype_struct( - MAGIC_NESTEDVALUE, CastVisitor::(std::marker::PhantomData)) + super::magic::input_value_via(deserializer) } //---------------------------------------------------------------------------