From 67bf47a5c9a57f64af108ef762219f74db687cea Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Sun, 24 May 2020 13:47:42 +0200 Subject: [PATCH] Less safe but drastically more efficient raw-value (de)serialization --- implementations/rust/src/ser.rs | 16 +++--- implementations/rust/src/value/de.rs | 11 +++-- implementations/rust/src/value/ser.rs | 12 +++-- implementations/rust/src/value/value.rs | 66 +++++++++---------------- 4 files changed, 46 insertions(+), 59 deletions(-) diff --git a/implementations/rust/src/ser.rs b/implementations/rust/src/ser.rs index 95c0a9a..5ba759d 100644 --- a/implementations/rust/src/ser.rs +++ b/implementations/rust/src/ser.rs @@ -4,7 +4,7 @@ use super::value::{ Value, NestedValue, PlainValue, Domain, NullDomain, DecodePlaceholderMap, EncodePlaceholderMap, invert_map, - Decoder, Encoder, to_value, + Encoder, }; type Result = std::result::Result; @@ -185,11 +185,15 @@ impl<'a, W: Writer, N: NestedValue, D: Domain> serde::Serializer for &'a mut fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> where T: Serialize { - if name == crate::value::value::MAGIC { - let v0: N = to_value(value)?; - let mut buf: &[u8] = v0.value().as_bytestring().ok_or_else(magic_error)?; - let v1: N = Decoder::new(&mut buf, None).next().or_else(|_| Err(magic_error()))?; - Encoder::new(&mut self.write, self.placeholders.as_ref()).write(&v1)?; + 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(&mut self.write, self.placeholders.as_ref()).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(&mut self.write, self.placeholders.as_ref()).write(v)?; Ok(()) } else { // TODO: This is apparently discouraged, and we should apparently just serialize `value`? diff --git a/implementations/rust/src/value/de.rs b/implementations/rust/src/value/de.rs index 79ed467..4801ac9 100644 --- a/implementations/rust/src/value/de.rs +++ b/implementations/rust/src/value/de.rs @@ -201,11 +201,12 @@ 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 { - let mut buf: Vec = Vec::new(); - crate::value::Encoder::new(&mut buf, None).write(self.input) - .or_else(|_e| Err(Error::InternalMagicError))?; - visitor.visit_byte_buf(buf) + 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)))?; diff --git a/implementations/rust/src/value/ser.rs b/implementations/rust/src/value/ser.rs index d9be201..1d9ad11 100644 --- a/implementations/rust/src/value/ser.rs +++ b/implementations/rust/src/value/ser.rs @@ -119,10 +119,14 @@ 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 { - let v: crate::value::PlainValue = to_value(value)?; - let mut buf: &[u8] = v.value().as_bytestring().ok_or(Error::InternalMagicError)?; - crate::value::Decoder::new(&mut buf, None).next().or(Err(Error::InternalMagicError)) + 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()) diff --git a/implementations/rust/src/value/value.rs b/implementations/rust/src/value/value.rs index 23d767e..5acc8fe 100644 --- a/implementations/rust/src/value/value.rs +++ b/implementations/rust/src/value/value.rs @@ -549,67 +549,45 @@ impl, D: Domain> Index<&N> for Value { //--------------------------------------------------------------------------- // This part is a terrible hack -pub static MAGIC: &str = "$____Preserves_Value"; - -#[derive(serde::Serialize)] -#[serde(rename = "$____Preserves_Value")] -struct ValueWrapper(#[serde(with = "serde_bytes")] Vec); - -struct ValueWrapperVisitor; - -impl<'de> serde::de::Visitor<'de> for ValueWrapperVisitor { - type Value = ValueWrapper; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "an encoded value wrapper") - } - - fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error { - Ok(ValueWrapper(Vec::from(v))) - } -} - -impl<'de> serde::Deserialize<'de> for ValueWrapper { - fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { - deserializer.deserialize_newtype_struct(MAGIC, ValueWrapperVisitor) - } -} +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 { - let mut buf: Vec = Vec::new(); - crate::value::Encoder::new(&mut buf, None).write_value(self) - .or_else(|_| Err(serde::ser::Error::custom("Internal error")))?; - ValueWrapper(buf).serialize(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) } } impl<'de, N: NestedValue, Dom: Domain> serde::Deserialize<'de> for Value { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { - let ValueWrapper(buf) = ValueWrapper::deserialize(deserializer)?; - let v: N = crate::value::Decoder::new(&mut &buf[..], None).next() - .or_else(|_| Err(serde::de::Error::custom("Internal error")))?; - Ok(v.value_owned()) + deserializer.deserialize_newtype_struct( + MAGIC_VALUE, CastVisitor::>(std::marker::PhantomData)) } } pub fn serialize_nested_value(v: &N, serializer: S) -> - Result where S: serde::Serializer, N: NestedValue + Result where S: serde::Serializer, N: NestedValue + serde::Serialize { - use serde::Serialize; - let mut buf: Vec = Vec::new(); - crate::value::Encoder::new(&mut buf, None).write(v) - .or_else(|_| Err(serde::ser::Error::custom("Internal error")))?; - ValueWrapper(buf).serialize(serializer) + serializer.serialize_newtype_struct(MAGIC_NESTEDVALUE, &(Box::into_raw(Box::new(v)) as u64)) } pub fn deserialize_nested_value<'de, D, N, Dom: Domain>(deserializer: D) -> - Result where D: serde::Deserializer<'de>, N: NestedValue + Result where D: serde::Deserializer<'de>, N: NestedValue + serde::Deserialize<'de> { - use serde::Deserialize; - let ValueWrapper(buf) = ValueWrapper::deserialize(deserializer)?; - crate::value::Decoder::new(&mut &buf[..], None).next() - .or_else(|_| Err(serde::de::Error::custom("Internal error"))) + deserializer.deserialize_newtype_struct( + MAGIC_NESTEDVALUE, CastVisitor::(std::marker::PhantomData)) } //---------------------------------------------------------------------------