Improve (!) safety at the expense of speed: 155kHz -> 115kHz :-/

This commit is contained in:
Tony Garnock-Jones 2020-05-26 09:08:17 +02:00
parent b122d6e2e0
commit c30154e0c8
7 changed files with 108 additions and 62 deletions

View File

@ -29,7 +29,7 @@ mod dom {
}
}
fn as_preserves<N: NestedValue<Self>>(&self) -> Result<N, std::io::Error> {
fn as_preserves<N: NestedValue<D>, D: Domain>(&self) -> Result<N, std::io::Error> {
Ok(Value::symbol(&format!("Dom::{:?}", self)).wrap())
}
}

View File

@ -144,22 +144,18 @@ impl<'a, 'b, W: Writer, N: NestedValue<D>, D: Domain> serde::Serializer for &'a
fn serialize_newtype_struct<T: ?Sized>(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<N, D>) };
let v: &Value<N, D> = *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()?)
}
}
}

View File

@ -251,17 +251,14 @@ impl<'de, 'a, N: NestedValue<D>, D: 'de + Domain> serde::de::Deserializer<'de>
fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V)
-> Result<V::Value, D> where V: Visitor<'de>
{
if name == crate::value::value::MAGIC_VALUE {
let v: Box<Value<N, D>> = 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<N> = 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)
}
}
}

View File

@ -0,0 +1,65 @@
use super::{
NullDomain,
value::{
ArcValue,
NestedValue,
Domain,
},
};
pub static MAGIC: &str = "$____Preserves_Serde_Magic";
pub type IOValue = ArcValue<NullDomain>;
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<E>(self, v: u64) -> Result<Self::Value, E> where E: serde::de::Error {
let b = unsafe { Box::from_raw(v as *mut IOValue) };
Ok(*b)
}
}
pub fn output_value<S: serde::Serializer>(serializer: S, v: IOValue) ->
Result<S::Ok, S::Error>
{
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<IOValue, D::Error>
{
deserializer.deserialize_newtype_struct(MAGIC, IOValueVisitor)
}
pub fn input_value_via<'de, D: serde::Deserializer<'de>, N: NestedValue<Dom>, Dom: Domain>(deserializer: D) ->
Result<N, D::Error>
{
Ok(input_value(deserializer)?.copy_via(&|_| unreachable!()))
}
//---------------------------------------------------------------------------
pub fn receive_output_value<T: ?Sized>(name: &'static str, magic_value: &T) -> Option<IOValue> {
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<F>(name: &'static str, f: F) -> Option<u64>
where F: FnOnce() -> IOValue
{
if name == MAGIC {
let b: Box<IOValue> = Box::new(f());
Some(Box::into_raw(b) as u64)
} else {
None
}
}

View File

@ -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;

View File

@ -134,17 +134,12 @@ impl<N: NestedValue<D>, D: Domain> serde::Serializer for Serializer<N, D> {
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) ->
Result<Self::Ok> 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<N, D>) };
let v: &Value<N, D> = *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())
}
}
}

View File

@ -19,7 +19,7 @@ pub trait Domain: Sized + Debug + Clone + Eq + Hash + Ord {
enc.write(&self.as_preserves()?)
}
fn as_preserves<N: NestedValue<Self>>(&self) -> Result<N, std::io::Error> {
fn as_preserves<N: NestedValue<D>, D: Domain>(&self) -> Result<N, std::io::Error> {
Err(std::io::Error::new(std::io::ErrorKind::InvalidData,
format!("Cannot Preserves-encode domain-specific value {:?}",
self)))
@ -54,9 +54,13 @@ pub trait NestedValue<D: Domain>: Sized + Debug + Clone + Eq + Hash + Ord {
self.value().copy_via(f))
}
fn copy_via_id<M: NestedValue<D>,>(&self) -> M {
fn copy_via_id<M: NestedValue<D>>(&self) -> M {
self.copy_via(&|d| Value::Domain(d.clone()))
}
fn copy_to_null_domain<M: NestedValue<super::NullDomain>>(&self) -> M {
self.copy_via(&|d| d.as_preserves::<M, super::NullDomain>().unwrap().value_owned())
}
}
/// The `Value`s from the specification.
@ -533,6 +537,10 @@ impl<N: NestedValue<D>, D: Domain> Value<N, D> {
Value::Domain(d) => f(d),
}
}
pub fn copy_to_null_domain<M: NestedValue<super::NullDomain>>(&self) -> Value<M, super::NullDomain> {
self.copy_via(&|d| d.as_preserves::<M, super::NullDomain>().unwrap().value_owned())
}
}
impl<N: NestedValue<D>, D: Domain> Index<usize> for Value<N, D> {
@ -560,45 +568,28 @@ impl<N: NestedValue<D>, D: Domain> Index<&N> for Value<N, D> {
//---------------------------------------------------------------------------
// This part is a terrible hack
pub static MAGIC_VALUE: &str = "$____Preserves_Value";
pub static MAGIC_NESTEDVALUE: &str = "$____Preserves_NestedValue";
impl<N: NestedValue<D>, D: Domain> serde::Serialize for Value<N, D> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
serializer.serialize_newtype_struct(MAGIC_VALUE, &(Box::into_raw(Box::new(self)) as u64))
}
}
struct CastVisitor<T>(std::marker::PhantomData<T>);
impl<'de, T> serde::de::Visitor<'de> for CastVisitor<T> {
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<E>(self, v: u64) -> Result<Self::Value, E> 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>, Dom: Domain> serde::Deserialize<'de> for Value<N, Dom> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
deserializer.deserialize_newtype_struct(
MAGIC_VALUE, CastVisitor::<Value<N, Dom>>(std::marker::PhantomData))
Ok(super::magic::input_value_via::<'de, D, N, Dom>(deserializer)?.value_owned())
}
}
pub fn serialize_nested_value<S, N, D: Domain>(v: &N, serializer: S) ->
Result<S::Ok, S::Error> where S: serde::Serializer, N: NestedValue<D> + 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<N, D::Error> where D: serde::Deserializer<'de>, N: NestedValue<Dom> + serde::Deserialize<'de>
{
deserializer.deserialize_newtype_struct(
MAGIC_NESTEDVALUE, CastVisitor::<N>(std::marker::PhantomData))
super::magic::input_value_via(deserializer)
}
//---------------------------------------------------------------------------