//! Test serialization to the `lexpr::Value` type use std::fmt::{self, Debug}; use serde::de; use serde_derive::{Deserialize, Serialize}; use lexpr::{sexp, Value}; use serde_lexpr::{error::Category, from_str, from_value, to_value}; use std::collections::HashMap; use std::collections::HashSet; fn test_serde(thing: &T, expected: &Value) where T: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug, { let value = to_value(thing).unwrap(); assert_eq!(&value, expected); let deserialized: T = from_value(&value).unwrap(); assert_eq!(&deserialized, thing); } fn deser_error(s: &str) -> Option<(Category, Option<(usize, usize)>)> where T: serde::de::DeserializeOwned, { from_str::(s) .err() .map(|e| (e.classify(), e.location().map(|l| (l.line(), l.column())))) } #[test] fn test_int() { let n = 4223; test_serde(&n, &sexp!(4223)); } #[test] fn test_char() { test_serde(&'c', &sexp!('c')); } #[test] fn test_bytes() { let bytes = b"abc"; test_serde( &serde_bytes::ByteBuf::from(bytes.as_ref()), &Value::from(&bytes[..]), ); } #[test] fn test_vec() { let empty: Vec = vec![]; test_serde(&empty, &sexp!(())); test_serde(&vec![1, 2, 3, 4], &sexp!((1 2 3 4))); } #[test] fn test_hashmap() { let mut hm: HashMap = HashMap::new(); test_serde(&hm, &sexp!(())); hm.insert("one".to_string(), 1); #[rustfmt::skip] // needed to avoid mangling of the `sexp!` invokation. test_serde(&hm, &sexp!((("one" . 1)))); } #[test] fn test_hashset() { let mut hs: HashSet = HashSet::new(); test_serde(&hs, &sexp!(())); hs.insert("one".to_string()); test_serde(&hs, &sexp!(("one"))); } #[test] fn test_unit() { test_serde(&(), &sexp!(())); } #[test] fn test_tuples() { let tuple = (1, "Hello".to_string(), true); test_serde(&tuple, &sexp!(#(1 "Hello" #t))); } #[test] fn test_deser_list_as_tuple() { let tuple: (u32, String) = from_value(&sexp!((42 "Answer"))).unwrap(); assert_eq!(tuple, (42, "Answer".to_string())); } #[test] fn test_deser_vector() { let v: Vec = from_value(&sexp!(#(42 23))).unwrap(); assert_eq!(v, vec![42, 23]); } #[test] fn test_option() { let none: Option = None; test_serde(&none, &sexp!(())); test_serde(&Some("Hello".to_string()), &sexp!(("Hello"))); } #[test] fn test_basic_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Animal { Dog, Cat, Kangaroo, } test_serde(&Animal::Dog, &sexp!(Dog)); test_serde(&Animal::Cat, &sexp!(Cat)); test_serde(&Animal::Kangaroo, &sexp!(Kangaroo)); } #[test] fn test_tuple_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Greeting { Hello, GoodBye, Other(String), Counted(u32, String), } test_serde(&Greeting::Hello, &sexp!(Hello)); test_serde(&Greeting::GoodBye, &sexp!(GoodBye)); test_serde( &Greeting::Other("Farewell".into()), &sexp!((Other . "Farewell")), ); test_serde( &Greeting::Counted(42, "Have a nice day".into()), &sexp!((Counted 42 "Have a nice day")), ); } #[test] fn test_complex_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Complex { Unit, OptionSingleton(Option), Struct { s: Option, v: Vec, t: (u32, f64, String), }, } test_serde(&Complex::Unit, &sexp!(Unit)); test_serde(&Complex::OptionSingleton(None), &sexp!((OptionSingleton))); test_serde( &Complex::OptionSingleton(Some("hello".into())), &sexp!((OptionSingleton "hello")), ); let s = Complex::Struct { s: Some("hello".into()), v: vec![1, 2, 3], t: (23, 1.23, "good bye".to_string()), }; test_serde( &s, &sexp!((Struct (s "hello") (v . (1 2 3)) (t . #(23 1.23 "good bye")))), ); } #[test] fn test_unit_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Unit; test_serde(&Unit, &sexp!(())); } #[test] fn test_empty_tuple_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Unit(); test_serde(&Unit(), &sexp!(#())); } #[test] fn test_newtype_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Newtype(u32); test_serde(&Newtype(42), &sexp!(42)); } #[test] fn test_empty_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Unit {} test_serde(&Unit {}, &sexp!(())); } #[test] fn test_empty_tuple_variant() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Empty { Tuplish(), } test_serde(&Empty::Tuplish {}, &sexp!((Tuplish))); } #[test] fn test_empty_struct_variant() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Empty { Structish {}, } test_serde(&Empty::Structish {}, &sexp!((Structish))); } #[test] fn test_basic_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Basic { foo: i64, bar: String, baz: bool, } let thing = Basic { foo: -324, bar: "Hello World".to_owned(), baz: true, }; test_serde( &thing, &sexp!(((foo . -324) (bar . "Hello World") (baz . #t))), ); } #[test] fn test_parse_error_eof() { assert_eq!( deser_error::("\""), Some((Category::Eof, Some((1, 1)))) ); assert_eq!( deser_error::("\"\\x43"), Some((Category::Eof, Some((1, 5)))) ); } #[derive(Debug, Eq, PartialEq)] struct ConsAccessTestStruct(Vec); struct ConsAccessTestVisitor; impl<'de> de::Visitor<'de> for ConsAccessTestVisitor { type Value = ConsAccessTestStruct; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a sequence of integers") } fn visit_seq(self, mut seq: A) -> Result where A: de::SeqAccess<'de>, { let mut result = Vec::new(); while let Some(element) = seq.next_element()? { result.push(element); } Ok(ConsAccessTestStruct(result)) } } impl<'de> de::Deserialize<'de> for ConsAccessTestStruct { fn deserialize>(deserializer: D) -> Result { deserializer.deserialize_any(ConsAccessTestVisitor) } } #[test] fn test_deserialize_any_cons() { let deserialized: ConsAccessTestStruct = from_value(&Value::cons(1, 2)).unwrap(); assert_eq!(deserialized, ConsAccessTestStruct(vec![1, 2])); }