use serde::Deserialize;
use serde::de::{
self, DeserializeSeed, EnumAccess, MapAccess, SeqAccess,
VariantAccess, Visitor,
};
use crate::builtins::Builtin;
use crate::error::Error;
pub type Result<T> = std::result::Result<T, Error>;
use crate::nkgc::PV;
use crate::swym::SwymDb;
pub struct Deserializer<'de> {
input: PV,
symdb: &'de SwymDb,
}
impl<'de> Deserializer<'de> {
pub fn from_pv(input: PV, vm: &'de SwymDb) -> Self {
Deserializer { input, symdb: vm }
}
}
pub fn from_pv<'a, 'de: 'a, T>(s: PV, vm: &'de SwymDb) -> Result<T>
where
T: Deserialize<'a>,
{
let mut deserializer = Deserializer::from_pv(s, vm);
let t = T::deserialize(&mut deserializer)?;
Ok(t)
}
impl<'de> Deserializer<'de> {
}
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self.input {
PV::Ref(_) => todo!(),
PV::Sym(_) => self.deserialize_identifier(visitor),
PV::Int(_) => self.deserialize_i32(visitor),
PV::UInt(_) => self.deserialize_u64(visitor),
PV::Real(_) => self.deserialize_f32(visitor),
PV::Bool(_) => self.deserialize_bool(visitor),
PV::Char(_) => self.deserialize_char(visitor),
PV::Nil => self.deserialize_unit(visitor),
}
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_bool(self.input.try_into()?)
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_i8(self.input.try_into()?)
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_i16(self.input.try_into()?)
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_i32(self.input.try_into()?)
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_i64(self.input.try_into()?)
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_u8(self.input.try_into()?)
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_u16(self.input.try_into()?)
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_u32(self.input.try_into()?)
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_u64(self.input.try_into()?)
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_f32(self.input.try_into()?)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_f64(self.input.try_into()?)
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_char(self.input.try_into()?)
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
with_ref!(self.input, String(s) => { visitor.visit_borrowed_str((*s).as_ref()) })
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_str(visitor)
}
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
unimplemented!()
}
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
unimplemented!()
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if self.input == PV::Nil {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
todo!()
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
_visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
todo!()
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
_visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
todo!()
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_seq(CommaSeparated::new(self))
}
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_seq(CommaSeparated::new(self))
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
_visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
todo!()
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_map(CommaSeparated::new(self))
}
fn deserialize_struct<V>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_map(CommaSeparated::new(self))
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_enum(Enum::new(self))
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if let Some(sym) = self.input.op() {
visitor.visit_str(sym.as_ref())
} else if let PV::Sym(sym) = self.input {
if let Some(ident) = sym.as_ref().strip_prefix(':') {
visitor.visit_str(ident)
} else {
Err(error!(TypeError,
expect: Builtin::Keyword,
got: Builtin::Symbol))
}
} else {
Err(error!(TypeError,
expect: Builtin::Symbol,
got: self.input.bt_type_of()))
}
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_any(visitor)
}
}
struct CommaSeparated<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
}
impl<'a, 'de> CommaSeparated<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self {
CommaSeparated {
de,
}
}
}
impl<'de, 'a> SeqAccess<'de> for CommaSeparated<'a, 'de> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
where
T: DeserializeSeed<'de>,
{
if self.de.input == PV::Nil {
return Ok(None);
}
let mut head = Deserializer { input: self.de.input.car().unwrap(),
symdb: self.de.symdb };
let res = seed.deserialize(&mut head).map(Some);
self.de.input = self.de.input.cdr().unwrap();
res
}
}
impl<'de, 'a> MapAccess<'de> for CommaSeparated<'a, 'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
if self.de.input == PV::Nil {
return Ok(None);
}
let mut head = Deserializer { input: self.de.input.car().unwrap(),
symdb: self.de.symdb };
let res = seed.deserialize(&mut head).map(Some);
self.de.input = self.de.input.cdr().unwrap();
res
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
let mut head = Deserializer { input: self.de.input.car().unwrap(),
symdb: self.de.symdb };
let res = seed.deserialize(&mut head);
self.de.input = self.de.input.cdr().unwrap();
res
}
}
struct Enum<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
}
impl<'a, 'de> Enum<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self {
Enum { de }
}
}
impl<'de, 'a> EnumAccess<'de> for Enum<'a, 'de> {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
where
V: DeserializeSeed<'de>,
{
let val = seed.deserialize(&mut *self.de)?;
Ok((val, self))
}
}
impl<'de, 'a> VariantAccess<'de> for Enum<'a, 'de> {
type Error = Error;
fn unit_variant(self) -> Result<()> {
unimplemented!("unit variant")
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
where
T: DeserializeSeed<'de>,
{
seed.deserialize(self.de)
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let inner = self.de.input;
let mut nde = Deserializer {
input: inner.cdr().unwrap_or(PV::Nil),
symdb: self.de.symdb,
};
de::Deserializer::deserialize_seq(&mut nde, visitor)
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
let inner = self.de.input;
let mut nde = Deserializer {
input: inner.cdr().unwrap_or(PV::Nil),
symdb: self.de.symdb,
};
de::Deserializer::deserialize_map(&mut nde, visitor)
}
}
#[cfg(test)]
mod tests {
use serde::Serialize;
use crate::{r8vm::R8VM, nkgc::SymID};
use super::*;
#[test]
fn deser_basic_types() {
let mut vm = R8VM::no_std();
let s = vm.eval(r#" "test" "#).unwrap();
let out_s: String = from_pv(s, &vm.mem.symdb).unwrap();
assert_eq!(out_s, "test");
let s = vm.eval(r#" 123 "#).unwrap();
let out_s: u32 = from_pv(s, &vm.mem.symdb).unwrap();
assert_eq!(out_s, 123);
let s = vm.eval(r#" -123 "#).unwrap();
let out_s = from_pv::<u32>(s, &vm.mem.symdb);
assert!(out_s.is_err());
let sigma = 0.000001;
let s = vm.eval(r#" 123.0 "#).unwrap();
let out_s: f32 = from_pv(s, &vm.mem.symdb).unwrap();
assert!(out_s - 123.0 < sigma);
let sigma = 0.000001;
let s = vm.eval(r#" 123.0 "#).unwrap();
let out_s: f64 = from_pv(s, &vm.mem.symdb).unwrap();
assert!(out_s - 123.0 < sigma);
}
#[test]
fn test_enum_type() {
let mut vm = R8VM::no_std();
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd)]
#[serde(rename_all = "kebab-case")]
enum U {
A(u32, u32),
B(String, u32),
#[serde(rename_all = "kebab-case")]
C { key: String,
key_2: u32 },
D { sym: SymID },
}
let s = vm.eval(r#" '(a 10 12) "#).unwrap();
let u = from_pv::<U>(s, &vm.mem.symdb).unwrap();
assert_eq!(u, U::A(10, 12));
let s = vm.eval(r#" '(b "brittany was here" 12) "#).unwrap();
let u = from_pv::<U>(s, &vm.mem.symdb).unwrap();
assert_eq!(u, U::B("brittany was here".to_string(), 12));
let s = vm.eval(r#" '(c :key "brittany was here" :key-2 12) "#).unwrap();
let u = from_pv::<U>(s, &vm.mem.symdb).unwrap();
assert_eq!(u, U::C { key: "brittany was here".to_string(), key_2: 12 });
let s = vm.eval(r#" ((lambda (x y) `(c :key ,y :key-2 ,x)) 123 "ayy lmao") "#)
.unwrap();
let u = from_pv::<U>(s, &vm.mem.symdb).unwrap();
assert_eq!(u, U::C { key: "ayy lmao".to_string(), key_2: 123 });
}
}