use std::{
fmt,
ops::{Deref, DerefMut},
};
use crate::{
api::{Pushable, VmType},
base::types::ArcType,
interner::InternedStr,
serde::ser::{self, Serialize},
thread::{ActiveThread, Thread},
types::{VmIndex, VmTag},
value::{Def, RecordDef, ValueRepr},
Error, Result, Variants,
};
pub struct Ser<T>(pub T);
impl<T> VmType for Ser<T>
where
T: VmType,
{
type Type = T::Type;
fn make_type(thread: &Thread) -> ArcType {
T::make_type(thread)
}
}
impl<'vm, T> Pushable<'vm> for Ser<T>
where
T: Serialize,
{
fn vm_push(self, context: &mut ActiveThread<'vm>) -> Result<()> {
let mut serializer = Serializer::new(context);
self.0.serialize(&mut serializer)
}
}
impl ser::Error for Error {
fn custom<T>(msg: T) -> Self
where
T: fmt::Display,
{
Error::Message(format!("{}", msg))
}
}
pub struct Serializer<'a, 't: 'a> {
thread: &'t Thread,
context: &'a mut ActiveThread<'t>,
}
impl<'a, 't> Serializer<'a, 't> {
pub fn new(context: &'a mut ActiveThread<'t>) -> Self {
Serializer {
thread: context.thread(),
context,
}
}
fn to_value<T>(&mut self, value: T) -> Result<()>
where
T: Pushable<'t>,
{
value.vm_push(self.context)
}
fn alloc(&mut self, tag: VmTag, values: VmIndex) -> Result<()> {
let mut context = self.context.context();
let value = context.gc.alloc(Def {
tag: tag,
elems: &context.stack[context.stack.len() - values..],
})?;
context.stack.pop_many(values);
context.stack.push(Variants::from(value));
Ok(())
}
fn alloc_record(&mut self, fields: &[InternedStr], values: VmIndex) -> Result<()> {
let mut context = self.context.context();
let value = context.gc.alloc(RecordDef {
elems: &context.stack[context.stack.len() - values..],
fields,
})?;
context.stack.pop_many(values);
context.stack.push(Variants::from(value));
Ok(())
}
}
#[doc(hidden)]
pub struct RecordSerializer<'s, 'a: 's, 'vm: 'a> {
serializer: &'s mut Serializer<'a, 'vm>,
variant_index: VmTag,
values: VmIndex,
fields: Vec<InternedStr>,
}
impl<'s, 'a, 'vm> Deref for RecordSerializer<'s, 'a, 'vm> {
type Target = Serializer<'a, 'vm>;
fn deref(&self) -> &Self::Target {
self.serializer
}
}
impl<'s, 'a, 'vm> DerefMut for RecordSerializer<'s, 'a, 'vm> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.serializer
}
}
impl<'s, 'a, 'vm> RecordSerializer<'s, 'a, 'vm> {
fn new(serializer: &'s mut Serializer<'a, 'vm>, variant_index: u32) -> Self {
RecordSerializer {
serializer: serializer,
variant_index: variant_index,
values: 0,
fields: Vec::new(),
}
}
}
impl<'s, 'a, 'vm> ser::Serializer for &'s mut Serializer<'a, 'vm> {
type Ok = ();
type Error = Error;
type SerializeSeq = RecordSerializer<'s, 'a, 'vm>;
type SerializeTuple = RecordSerializer<'s, 'a, 'vm>;
type SerializeTupleStruct = RecordSerializer<'s, 'a, 'vm>;
type SerializeTupleVariant = RecordSerializer<'s, 'a, 'vm>;
type SerializeMap = RecordSerializer<'s, 'a, 'vm>;
type SerializeStruct = RecordSerializer<'s, 'a, 'vm>;
type SerializeStructVariant = RecordSerializer<'s, 'a, 'vm>;
fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
self.to_value(v)
}
fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
self.serialize_i64(v as i64)
}
fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
self.serialize_i64(v as i64)
}
fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
self.serialize_i64(v as i64)
}
fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
self.to_value(v as isize)
}
fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
self.serialize_u64(v as u64)
}
fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
self.serialize_u64(v as u64)
}
fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
self.serialize_u64(v as u64)
}
fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
self.to_value(v as isize)
}
fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
self.serialize_f64(v as f64)
}
fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
self.to_value(v)
}
fn serialize_char(self, v: char) -> Result<Self::Ok> {
self.serialize_str(&v.to_string())
}
fn serialize_str(self, v: &str) -> Result<Self::Ok> {
self.to_value(v)
}
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
self.to_value(v)
}
fn serialize_none(self) -> Result<Self::Ok> {
self.serialize_unit()
}
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok>
where
T: ?Sized + Serialize,
{
value.serialize(self)
}
fn serialize_unit(self) -> Result<Self::Ok> {
self.context.push(ValueRepr::Tag(0));
Ok(())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
self.serialize_unit()
}
fn serialize_unit_variant(
self,
_name: &'static str,
variant_index: u32,
_variant: &'static str,
) -> Result<Self::Ok> {
self.context.push(ValueRepr::Tag(variant_index));
Ok(())
}
fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Self::Ok>
where
T: ?Sized + Serialize,
{
value.serialize(self)
}
fn serialize_newtype_variant<T>(
self,
_name: &'static str,
variant_index: u32,
_variant: &'static str,
value: &T,
) -> Result<Self::Ok>
where
T: ?Sized + Serialize,
{
value.serialize(&mut *self)?;
self.alloc(variant_index, 1)
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
Ok(RecordSerializer::new(self, 0))
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant> {
Ok(RecordSerializer::new(self, variant_index))
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
Ok(RecordSerializer::new(self, 0))
}
fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
self.serialize_map(Some(len))
}
fn serialize_struct_variant(
self,
_name: &'static str,
variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant> {
Ok(RecordSerializer::new(self, variant_index))
}
}
impl<'s, 'a, 'vm> ser::SerializeSeq for RecordSerializer<'s, 'a, 'vm> {
type Ok = ();
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
value.serialize(&mut **self)?;
self.values += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok> {
self.serializer.alloc(self.variant_index, self.values)
}
}
impl<'s, 'a, 'vm> ser::SerializeTuple for RecordSerializer<'s, 'a, 'vm> {
type Ok = ();
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
value.serialize(&mut **self)?;
self.values += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok> {
self.serializer.alloc(self.variant_index, self.values)
}
}
impl<'s, 'a, 'vm> ser::SerializeTupleStruct for RecordSerializer<'s, 'a, 'vm> {
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
value.serialize(&mut **self)?;
self.values += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok> {
self.serializer.alloc(self.variant_index, self.values)
}
}
impl<'s, 'a, 'vm> ser::SerializeTupleVariant for RecordSerializer<'s, 'a, 'vm> {
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
value.serialize(&mut **self)?;
self.values += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok> {
self.serializer.alloc(self.variant_index, self.values)
}
}
impl<'s, 'a, 'vm> ser::SerializeMap for RecordSerializer<'s, 'a, 'vm> {
type Ok = ();
type Error = Error;
fn serialize_key<T>(&mut self, _key: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
Ok(())
}
fn serialize_value<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
value.serialize(&mut **self)?;
self.values += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok> {
self.serializer.alloc(self.variant_index, self.values)
}
}
impl<'s, 'a, 'vm> ser::SerializeStruct for RecordSerializer<'s, 'a, 'vm> {
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
let field = self.thread.global_env().intern(key)?;
self.fields.push(field);
value.serialize(&mut **self)?;
self.values += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok> {
self.serializer.alloc_record(&self.fields, self.values)
}
}
impl<'s, 'a, 'vm> ser::SerializeStructVariant for RecordSerializer<'s, 'a, 'vm> {
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
let field = self.thread.global_env().intern(key)?;
self.fields.push(field);
value.serialize(&mut **self)?;
self.values += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok> {
self.serializer.alloc_record(&self.fields, self.values)?;
self.serializer.alloc(self.variant_index, 1)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{thread::RootedThread, value::Value};
#[test]
fn bool() {
let thread = RootedThread::new();
assert_eq!(
true.marshal::<&Thread>(&thread).unwrap().get_value(),
&Value::tag(1)
);
}
}