#![cfg(feature = "serde")]
use intern::Interner;
use serde::de::*;
use std::cell::RefCell;
use std::fmt;
#[derive(Debug)]
pub struct WithInterner<'si, T> {
interner: &'si RefCell<Interner>,
value: T,
}
pub fn with_interner<'de, D: Deserializer<'de>>(deserializer: D, interner: &RefCell<Interner>) -> WithInterner<D> {
WithInterner {
interner,
value: deserializer,
}
}
macro_rules! wrap {
($self:ident . $f:ident($($value:ident),+ $(;$prev_args:expr)*)) => {{
$(let $value = WithInterner {
interner: $self.interner,
value: $value,
};)+
$self.value.$f($($prev_args,)* $($value),+)
}}
}
macro_rules! forward_deserializer {
($name:ident $(, $arg:ident: $ty:ty)*) => {
fn $name<V: Visitor<'de>>(self, $($arg: $ty,)* visitor: V) -> Result<V::Value, D::Error> {
wrap!(self.$name(visitor $(;$arg)*))
}
}
}
impl<'si, 'de, D: Deserializer<'de>> Deserializer<'de> for WithInterner<'si, D> {
type Error = D::Error;
forward_deserializer!(deserialize_any);
forward_deserializer!(deserialize_bool);
forward_deserializer!(deserialize_u8);
forward_deserializer!(deserialize_u16);
forward_deserializer!(deserialize_u32);
forward_deserializer!(deserialize_u64);
forward_deserializer!(deserialize_i8);
forward_deserializer!(deserialize_i16);
forward_deserializer!(deserialize_i32);
forward_deserializer!(deserialize_i64);
forward_deserializer!(deserialize_f32);
forward_deserializer!(deserialize_f64);
forward_deserializer!(deserialize_char);
forward_deserializer!(deserialize_str);
forward_deserializer!(deserialize_string);
forward_deserializer!(deserialize_unit);
forward_deserializer!(deserialize_option);
forward_deserializer!(deserialize_seq);
forward_deserializer!(deserialize_bytes);
forward_deserializer!(deserialize_byte_buf);
forward_deserializer!(deserialize_map);
forward_deserializer!(deserialize_unit_struct, name: &'static str);
forward_deserializer!(deserialize_tuple_struct, name: &'static str, len: usize);
forward_deserializer!(deserialize_struct, name: &'static str, fields: &'static [&'static str]);
forward_deserializer!(deserialize_identifier);
forward_deserializer!(deserialize_tuple, len: usize);
forward_deserializer!(deserialize_enum, name: &'static str, variants: &'static [&'static str]);
forward_deserializer!(deserialize_ignored_any);
fn deserialize_newtype_struct<V: Visitor<'de>>(self, name: &'static str, visitor: V) -> Result<V::Value, Self::Error> {
if name == "Symbol" {
let v = ToSymbol {
interner: self.interner,
value: visitor,
};
self.value.deserialize_newtype_struct(name, v)
} else {
wrap!(self.deserialize_newtype_struct(visitor; name))
}
}
}
macro_rules! forward_visitor {
($name:ident($($arg:ident: $ty:ty),*)) => {
fn $name<E: Error>(self $(, $arg: $ty)*) -> Result<V::Value, E> {
self.value.$name($($arg),*)
}
};
($name:ident <$n:ident: $ty:ident>) => {
fn $name<$n: $ty<'de>>(self, value: $n) -> Result<V::Value, $n::Error> {
wrap!(self.$name(value))
}
};
}
impl<'si, 'de, V: Visitor<'de>> Visitor<'de> for WithInterner<'si, V> {
type Value = V::Value;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.value.expecting(fmt)
}
forward_visitor!(visit_bool(v: bool));
forward_visitor!(visit_i8(v: i8));
forward_visitor!(visit_i16(v: i16));
forward_visitor!(visit_i32(v: i32));
forward_visitor!(visit_i64(v: i64));
forward_visitor!(visit_u8(v: u8));
forward_visitor!(visit_u16(v: u16));
forward_visitor!(visit_u32(v: u32));
forward_visitor!(visit_u64(v: u64));
forward_visitor!(visit_f32(v: f32));
forward_visitor!(visit_f64(v: f64));
forward_visitor!(visit_char(v: char));
forward_visitor!(visit_str(v: &str));
forward_visitor!(visit_string(v: String));
forward_visitor!(visit_borrowed_str(v: &'de str));
forward_visitor!(visit_bytes(v: &[u8]));
forward_visitor!(visit_borrowed_bytes(v: &'de [u8]));
forward_visitor!(visit_byte_buf(v: Vec<u8>));
forward_visitor!(visit_none());
forward_visitor!(visit_some<D: Deserializer>);
forward_visitor!(visit_unit());
forward_visitor!(visit_newtype_struct<D: Deserializer>);
forward_visitor!(visit_seq<A: SeqAccess>);
forward_visitor!(visit_map<A: MapAccess>);
forward_visitor!(visit_enum<A: EnumAccess>);
}
impl<'si, 'de, A: SeqAccess<'de>> SeqAccess<'de> for WithInterner<'si, A> {
type Error = A::Error;
fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T) -> Result<Option<T::Value>, A::Error> {
wrap!(self.next_element_seed(seed))
}
fn size_hint(&self) -> Option<usize> {
self.value.size_hint()
}
}
impl<'si, 'de, A: MapAccess<'de>> MapAccess<'de> for WithInterner<'si, A> {
type Error = A::Error;
fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>, A::Error> {
wrap!(self.next_key_seed(seed))
}
fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value, A::Error> {
wrap!(self.next_value_seed(seed))
}
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
fn next_entry_seed<K: DeserializeSeed<'de>, V: DeserializeSeed<'de>>(&mut self, key_seed: K, value_seed: V) -> Result<Option<(K::Value, V::Value)>, A::Error> {
wrap!(self.next_entry_seed(key_seed, value_seed))
}
}
impl<'si, 'de, A: EnumAccess<'de>> EnumAccess<'de> for WithInterner<'si, A> {
type Error = A::Error;
type Variant = WithInterner<'si, A::Variant>;
fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant), A::Error> {
let (value, variant) = wrap!(self.variant_seed(seed))?;
let variant = WithInterner {
interner: self.interner,
value: variant,
};
Ok((value, variant))
}
}
impl<'si, 'de, A: VariantAccess<'de>> VariantAccess<'de> for WithInterner<'si, A> {
type Error = A::Error;
fn unit_variant(self) -> Result<(), Self::Error> {
self.value.unit_variant()
}
fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value, A::Error> {
wrap!(self.newtype_variant_seed(seed))
}
fn tuple_variant<V: Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value, A::Error> {
wrap!(self.tuple_variant(visitor; len))
}
fn struct_variant<V: Visitor<'de>>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, A::Error> {
wrap!(self.struct_variant(visitor; fields))
}
}
impl<'si, 'de, T: DeserializeSeed<'de>> DeserializeSeed<'de> for WithInterner<'si, T> {
type Value = T::Value;
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<T::Value, D::Error> {
wrap!(self.deserialize(deserializer))
}
}
struct ToSymbol<'si, T> {
interner: &'si RefCell<Interner>,
value: T,
}
impl<'si, 'de, V: Visitor<'de>> Visitor<'de> for ToSymbol<'si, V> {
type Value = V::Value;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("string")
}
fn visit_str<E: Error>(self, v: &str) -> Result<V::Value, E> {
let symbol: usize = self.interner.borrow_mut().intern(v).into();
self.value.visit_u64(symbol as u64)
}
fn visit_string<E: Error>(self, v: String) -> Result<V::Value, E> {
let symbol: usize = self.interner.borrow_mut().intern(v).into();
self.value.visit_u64(symbol as u64)
}
fn visit_newtype_struct<D: Deserializer<'de>>(self, deserializer: D) -> Result<V::Value, D::Error> {
let deserializer = ToSymbol {
interner: self.interner,
value: deserializer,
};
self.value.visit_newtype_struct(deserializer)
}
}
impl<'si, 'de, D: Deserializer<'de>> Deserializer<'de> for ToSymbol<'si, D> {
type Error = D::Error;
fn deserialize_any<V: Visitor<'de>>(self, _: V) -> Result<V::Value, D::Error> {
unreachable!()
}
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, D::Error> {
let visitor = ToSymbol {
interner: self.interner,
value: visitor,
};
self.value.deserialize_str(visitor)
}
forward_to_deserialize_any! {
bool
i8 i16 i32 i64
u8 u16 u32
f32 f64
char
bytes
byte_buf
str
string
option
unit
unit_struct
newtype_struct
seq
tuple
tuple_struct
map
struct
enum
identifier
ignored_any
}
}
#[test]
fn test_deserialize_symbol() {
use intern::Symbol;
use serde_json::de::Deserializer;
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Foo {
a: String,
b: Option<Symbol>,
c: Vec<Symbol>,
d: (String, Symbol),
}
let mut interner = Interner::new();
let s2 = interner.intern("s2");
let s3 = interner.intern("s3");
let s4 = interner.intern("s4");
let expected = Foo {
a: "s1".to_owned(),
b: Some(s2),
c: vec![s3, s4],
d: ("s3".to_owned(), s4),
};
let mut deserializer = Deserializer::from_str(
r#"{
"a": "s1",
"b": "s2",
"c": ["s3", "s4"],
"d": ["s3", "s4"]
}"#,
);
let interner = RefCell::new(interner);
let deserializer = with_interner(&mut deserializer, &interner);
let actual = Foo::deserialize(deserializer).expect("deserialized");
assert_eq!(expected, actual);
}