forked from syndicate-lang/preserves
54 lines
1.6 KiB
Rust
54 lines
1.6 KiB
Rust
use super::repr::IOValue;
|
|
|
|
pub static MAGIC: &str = "$____Preserves_Serde_Magic";
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
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))
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn input_value<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<IOValue, D::Error>
|
|
{
|
|
deserializer.deserialize_newtype_struct(MAGIC, IOValueVisitor)
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
#[inline]
|
|
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
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn transmit_input_value<F>(name: &'static str, f: F) -> Result<Option<u64>, crate::error::Error>
|
|
where F: FnOnce() -> Result<IOValue, crate::error::Error>
|
|
{
|
|
if name == MAGIC {
|
|
let b: Box<IOValue> = Box::new(f()?);
|
|
Ok(Some(Box::into_raw(b) as u64))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|