diff --git a/extendr-api/tests/deserializer_tests.rs b/extendr-api/tests/deserializer_tests.rs index 0d5cba2576..187f248a04 100644 --- a/extendr-api/tests/deserializer_tests.rs +++ b/extendr-api/tests/deserializer_tests.rs @@ -1,174 +1,172 @@ -#[cfg(feature = "serde")] -mod test { - use extendr_api::deserializer::from_robj; - use extendr_api::prelude::*; - use serde::Deserialize; - - //////////////////////////////////////////////////////////////////////////////// - /// - /// Deserialize from a Robj. - /// - /// Like JSON, we can use a Robj as a storage format. - /// - /// For example if creating vectors from a RDS file or returning a structure - /// or just doing a conversion. - /// - #[test] - fn test_deserialize_robj() { - test! { - // In these tests, the wrapper is transparent and just tests the contents. - // So Int(i32) is actually testing i32. - - #[derive(Deserialize, PartialEq, Debug)] - struct Null; - assert_eq!(from_robj::(&r!(NULL)), Ok(Null)); - assert_eq!(from_robj::(&r!(1)), Err(Error::ExpectedNull(r!(1)))); - - #[derive(Deserialize, PartialEq, Debug)] - struct Int(i32); - assert_eq!(from_robj::(&r!(1)), Ok(Int(1))); - assert_eq!(from_robj::(&r!(1.0)), Ok(Int(1))); - assert_eq!(from_robj::(&r!(NULL)).is_err(), true); - - #[derive(Deserialize, PartialEq, Debug)] - struct RInt(Rint); - assert_eq!(from_robj::(&r!(1)), Ok(RInt(1.into()))); - assert_eq!(from_robj::(&r!(1.0)), Ok(RInt(1.into()))); - assert_eq!(from_robj::(&r!(Rint::na())).is_err(), true); - assert_eq!(from_robj::(&r!(NULL)).is_err(), true); - - #[derive(Deserialize, PartialEq, Debug)] - struct Float(f64); - assert_eq!(from_robj::(&r!(1)), Ok(Float(1.0))); - assert_eq!(from_robj::(&r!(1.0)), Ok(Float(1.0))); - assert_eq!(from_robj::(&r!(NULL)).is_err(), true); - - #[derive(Deserialize, PartialEq, Debug)] - struct RFloat(Rfloat); - assert_eq!(from_robj::(&r!(1)), Ok(RFloat(1.0.into()))); - assert_eq!(from_robj::(&r!(1.0)), Ok(RFloat(1.0.into()))); - assert_eq!(from_robj::(&r!(Rfloat::na())).is_err(), true); - assert_eq!(from_robj::(&r!(NULL)).is_err(), true); - - #[derive(Deserialize, PartialEq, Debug)] - struct Bool(bool); - assert_eq!(from_robj::(&r!(TRUE)), Ok(Bool(true))); - assert_eq!(from_robj::(&r!(FALSE)), Ok(Bool(false))); - assert_eq!(from_robj::(&r!(NULL)).is_err(), true); - - #[derive(Deserialize, PartialEq, Debug)] - struct RBool(Rbool); - assert_eq!(from_robj::(&r!(TRUE)), Ok(RBool(TRUE))); - assert_eq!(from_robj::(&r!(FALSE)), Ok(RBool(FALSE))); - assert_eq!(from_robj::(&r!(Rbool::na())).is_err(), true); - assert_eq!(from_robj::(&r!(NULL)).is_err(), true); - - #[derive(Deserialize, PartialEq, Debug)] - struct VInt(Vec); - assert_eq!(from_robj::(&r!(list!(1, 2))), Ok(VInt(vec![1, 2]))); - assert_eq!(from_robj::(&r!([1, 2])), Ok(VInt(vec![1, 2]))); - assert_eq!(from_robj::(&r!([1, 2, i32::na()])).is_err(), true); - - // Any integer type will do. - #[derive(Deserialize, PartialEq, Debug)] - struct VInt16(Vec); - assert_eq!(from_robj::(&r!(list!(1, 2))), Ok(VInt16(vec![1, 2]))); - assert_eq!(from_robj::(&r!([1, 2])), Ok(VInt16(vec![1, 2]))); - - #[derive(Deserialize, PartialEq, Debug)] - struct VFloat64(Vec); - assert_eq!(from_robj::(&r!(list!(1, 2))), Ok(VFloat64(vec![1., 2.]))); - assert_eq!(from_robj::(&r!([1, 2])), Ok(VFloat64(vec![1., 2.]))); - - #[derive(Deserialize, PartialEq, Debug)] - struct VBool(Vec); - assert_eq!(from_robj::(&r!(list!(TRUE, FALSE))), Ok(VBool(vec![true, false]))); - assert_eq!(from_robj::(&r!([TRUE, FALSE])), Ok(VBool(vec![true, false]))); - - #[derive(Deserialize, PartialEq, Debug)] - struct Str(String); - assert_eq!(from_robj::(&r!("xyz")), Ok(Str("xyz".into()))); - - #[derive(Deserialize, PartialEq, Debug)] - struct StrSlice<'a>(&'a str); - assert_eq!(from_robj::(&r!("xyz")), Ok(StrSlice("xyz"))); - - // Structs are mapped to named lists. - #[derive(Deserialize, PartialEq, Debug)] - struct Struct { a: i32, b: f64 } - assert_eq!(from_robj::(&r!(list!(a=1, b=2))), Ok(Struct{ a: 1, b: 2.0 })); - - // Enums are mapped to named lists of lists. - #[derive(Deserialize, PartialEq, Debug)] - enum Enum { - Unit, - Newtype(u32), - Tuple(u32, u32), - Struct { a: u32 }, - } - - let j = r!("Unit"); - let expected = Enum::Unit; - assert_eq!(expected, from_robj(&j).unwrap()); - - // If the name is wrong: - let j = r!("UnitX"); - assert_eq!(from_robj::(&j).is_err(), true); - - let j = r!(list!(Newtype=1)); - let expected = Enum::Newtype(1); - assert_eq!(expected, from_robj(&j).unwrap()); - - let j = r!(list!(Tuple=list!(1, 2))); - let expected = Enum::Tuple(1, 2); - assert_eq!(expected, from_robj(&j).unwrap()); - - let j = r!(list!(Struct=list!(a=1))); - let expected = Enum::Struct { a: 1 }; - assert_eq!(expected, from_robj(&j).unwrap()); - - // Many things will generate a Robj. - // But note that the original Robj will not be copied verbatim. - // The Deserialize trait for Robj can also be used to generate - // JSON and other formats for Robj. - #[derive(Deserialize, PartialEq, Debug)] - struct WrapRobj(Robj); - assert_eq!(from_robj::(&r!(TRUE)), Ok(WrapRobj(r!(TRUE)))); - assert_eq!(from_robj::(&r!(1)), Ok(WrapRobj(r!(1)))); - assert_eq!(from_robj::(&r!(1.0)), Ok(WrapRobj(r!(1.0)))); - assert_eq!(from_robj::(&r!("xyz")), Ok(WrapRobj(r!("xyz")))); - - // Sequences are always converted to lists. - assert_eq!(from_robj::(&r!([TRUE, FALSE])), Ok(WrapRobj(r!(list!(TRUE, FALSE))))); - assert_eq!(from_robj::(&r!([1, 2])), Ok(WrapRobj(r!(list!(1, 2))))); - - // If you use a wrapper type, conversions are more specific. - #[derive(Deserialize, PartialEq, Debug)] - struct RIntegers(Integers); - assert_eq!(from_robj::(&r!(1)), Ok(RIntegers(Integers::from_values([1])))); - assert_eq!(from_robj::(&r!([1, 2])), Ok(RIntegers(Integers::from_values([1, 2])))); - assert_eq!(from_robj::(&r!(1.0)).is_err(), true); - assert_eq!(from_robj::(&r!("xyz")).is_err(), true); - - #[derive(Deserialize, PartialEq, Debug)] - struct RDoubles(Doubles); - assert_eq!(from_robj::(&r!(1)), Ok(RDoubles(Doubles::from_values([1.0])))); - // assert_eq!(from_robj::(&r!([1, 2])), Ok(RDoubles(Doubles::from_values([1.0, 2.0])))); - assert_eq!(from_robj::(&r!([1.0, 2.0])), Ok(RDoubles(Doubles::from_values([1.0, 2.0])))); - assert_eq!(from_robj::(&r!("xyz")).is_err(), true); - - #[derive(Deserialize, PartialEq, Debug)] - struct RLogicals(Logicals); - assert_eq!(from_robj::(&r!(TRUE)), Ok(RLogicals(Logicals::from_values([TRUE])))); - assert_eq!(from_robj::(&r!([TRUE, FALSE, NA_LOGICAL])), Ok(RLogicals(Logicals::from_values([TRUE, FALSE, NA_LOGICAL])))); - assert_eq!(from_robj::(&r!("xyz")).is_err(), true); - - // This requires a PR that is not yet merged. - // #[derive(Deserialize, PartialEq, Debug)] - // struct RStrings(Strings); - // assert_eq!(from_robj::(&r!("xyz")), Ok(RStrings(Strings::from_values(["xyz"])))); - // assert_eq!(from_robj::(&r!(["a", "b"])), Ok(RStrings(Strings::from_values(["a", "b"])))); - // assert_eq!(from_robj::(&r!(0)).is_err(), true); +#![cfg(feature = "serde")] +use extendr_api::deserializer::from_robj; +use extendr_api::prelude::*; +use serde::Deserialize; + +//////////////////////////////////////////////////////////////////////////////// +/// +/// Deserialize from a Robj. +/// +/// Like JSON, we can use a Robj as a storage format. +/// +/// For example if creating vectors from a RDS file or returning a structure +/// or just doing a conversion. +/// +#[test] +fn test_deserialize_robj() { + test! { + // In these tests, the wrapper is transparent and just tests the contents. + // So Int(i32) is actually testing i32. + + #[derive(Deserialize, PartialEq, Debug)] + struct Null; + assert_eq!(from_robj::(&r!(NULL)), Ok(Null)); + assert_eq!(from_robj::(&r!(1)), Err(Error::ExpectedNull(r!(1)))); + + #[derive(Deserialize, PartialEq, Debug)] + struct Int(i32); + assert_eq!(from_robj::(&r!(1)), Ok(Int(1))); + assert_eq!(from_robj::(&r!(1.0)), Ok(Int(1))); + assert_eq!(from_robj::(&r!(NULL)).is_err(), true); + + #[derive(Deserialize, PartialEq, Debug)] + struct RInt(Rint); + assert_eq!(from_robj::(&r!(1)), Ok(RInt(1.into()))); + assert_eq!(from_robj::(&r!(1.0)), Ok(RInt(1.into()))); + assert_eq!(from_robj::(&r!(Rint::na())).is_err(), true); + assert_eq!(from_robj::(&r!(NULL)).is_err(), true); + + #[derive(Deserialize, PartialEq, Debug)] + struct Float(f64); + assert_eq!(from_robj::(&r!(1)), Ok(Float(1.0))); + assert_eq!(from_robj::(&r!(1.0)), Ok(Float(1.0))); + assert_eq!(from_robj::(&r!(NULL)).is_err(), true); + + #[derive(Deserialize, PartialEq, Debug)] + struct RFloat(Rfloat); + assert_eq!(from_robj::(&r!(1)), Ok(RFloat(1.0.into()))); + assert_eq!(from_robj::(&r!(1.0)), Ok(RFloat(1.0.into()))); + assert_eq!(from_robj::(&r!(Rfloat::na())).is_err(), true); + assert_eq!(from_robj::(&r!(NULL)).is_err(), true); + + #[derive(Deserialize, PartialEq, Debug)] + struct Bool(bool); + assert_eq!(from_robj::(&r!(TRUE)), Ok(Bool(true))); + assert_eq!(from_robj::(&r!(FALSE)), Ok(Bool(false))); + assert_eq!(from_robj::(&r!(NULL)).is_err(), true); + + #[derive(Deserialize, PartialEq, Debug)] + struct RBool(Rbool); + assert_eq!(from_robj::(&r!(TRUE)), Ok(RBool(TRUE))); + assert_eq!(from_robj::(&r!(FALSE)), Ok(RBool(FALSE))); + assert_eq!(from_robj::(&r!(Rbool::na())).is_err(), true); + assert_eq!(from_robj::(&r!(NULL)).is_err(), true); + + #[derive(Deserialize, PartialEq, Debug)] + struct VInt(Vec); + assert_eq!(from_robj::(&r!(list!(1, 2))), Ok(VInt(vec![1, 2]))); + assert_eq!(from_robj::(&r!([1, 2])), Ok(VInt(vec![1, 2]))); + assert_eq!(from_robj::(&r!([1, 2, i32::na()])).is_err(), true); + + // Any integer type will do. + #[derive(Deserialize, PartialEq, Debug)] + struct VInt16(Vec); + assert_eq!(from_robj::(&r!(list!(1, 2))), Ok(VInt16(vec![1, 2]))); + assert_eq!(from_robj::(&r!([1, 2])), Ok(VInt16(vec![1, 2]))); + + #[derive(Deserialize, PartialEq, Debug)] + struct VFloat64(Vec); + assert_eq!(from_robj::(&r!(list!(1, 2))), Ok(VFloat64(vec![1., 2.]))); + assert_eq!(from_robj::(&r!([1, 2])), Ok(VFloat64(vec![1., 2.]))); + + #[derive(Deserialize, PartialEq, Debug)] + struct VBool(Vec); + assert_eq!(from_robj::(&r!(list!(TRUE, FALSE))), Ok(VBool(vec![true, false]))); + assert_eq!(from_robj::(&r!([TRUE, FALSE])), Ok(VBool(vec![true, false]))); + + #[derive(Deserialize, PartialEq, Debug)] + struct Str(String); + assert_eq!(from_robj::(&r!("xyz")), Ok(Str("xyz".into()))); + + #[derive(Deserialize, PartialEq, Debug)] + struct StrSlice<'a>(&'a str); + assert_eq!(from_robj::(&r!("xyz")), Ok(StrSlice("xyz"))); + + // Structs are mapped to named lists. + #[derive(Deserialize, PartialEq, Debug)] + struct Struct { a: i32, b: f64 } + assert_eq!(from_robj::(&r!(list!(a=1, b=2))), Ok(Struct{ a: 1, b: 2.0 })); + + // Enums are mapped to named lists of lists. + #[derive(Deserialize, PartialEq, Debug)] + enum Enum { + Unit, + Newtype(u32), + Tuple(u32, u32), + Struct { a: u32 }, } + + let j = r!("Unit"); + let expected = Enum::Unit; + assert_eq!(expected, from_robj(&j).unwrap()); + + // If the name is wrong: + let j = r!("UnitX"); + assert_eq!(from_robj::(&j).is_err(), true); + + let j = r!(list!(Newtype=1)); + let expected = Enum::Newtype(1); + assert_eq!(expected, from_robj(&j).unwrap()); + + let j = r!(list!(Tuple=list!(1, 2))); + let expected = Enum::Tuple(1, 2); + assert_eq!(expected, from_robj(&j).unwrap()); + + let j = r!(list!(Struct=list!(a=1))); + let expected = Enum::Struct { a: 1 }; + assert_eq!(expected, from_robj(&j).unwrap()); + + // Many things will generate a Robj. + // But note that the original Robj will not be copied verbatim. + // The Deserialize trait for Robj can also be used to generate + // JSON and other formats for Robj. + #[derive(Deserialize, PartialEq, Debug)] + struct WrapRobj(Robj); + assert_eq!(from_robj::(&r!(TRUE)), Ok(WrapRobj(r!(TRUE)))); + assert_eq!(from_robj::(&r!(1)), Ok(WrapRobj(r!(1)))); + assert_eq!(from_robj::(&r!(1.0)), Ok(WrapRobj(r!(1.0)))); + assert_eq!(from_robj::(&r!("xyz")), Ok(WrapRobj(r!("xyz")))); + + // Sequences are always converted to lists. + assert_eq!(from_robj::(&r!([TRUE, FALSE])), Ok(WrapRobj(r!(list!(TRUE, FALSE))))); + assert_eq!(from_robj::(&r!([1, 2])), Ok(WrapRobj(r!(list!(1, 2))))); + + // If you use a wrapper type, conversions are more specific. + #[derive(Deserialize, PartialEq, Debug)] + struct RIntegers(Integers); + assert_eq!(from_robj::(&r!(1)), Ok(RIntegers(Integers::from_values([1])))); + assert_eq!(from_robj::(&r!([1, 2])), Ok(RIntegers(Integers::from_values([1, 2])))); + assert_eq!(from_robj::(&r!(1.0)).is_err(), true); + assert_eq!(from_robj::(&r!("xyz")).is_err(), true); + + #[derive(Deserialize, PartialEq, Debug)] + struct RDoubles(Doubles); + assert_eq!(from_robj::(&r!(1)), Ok(RDoubles(Doubles::from_values([1.0])))); + // assert_eq!(from_robj::(&r!([1, 2])), Ok(RDoubles(Doubles::from_values([1.0, 2.0])))); + assert_eq!(from_robj::(&r!([1.0, 2.0])), Ok(RDoubles(Doubles::from_values([1.0, 2.0])))); + assert_eq!(from_robj::(&r!("xyz")).is_err(), true); + + #[derive(Deserialize, PartialEq, Debug)] + struct RLogicals(Logicals); + assert_eq!(from_robj::(&r!(TRUE)), Ok(RLogicals(Logicals::from_values([TRUE])))); + assert_eq!(from_robj::(&r!([TRUE, FALSE, NA_LOGICAL])), Ok(RLogicals(Logicals::from_values([TRUE, FALSE, NA_LOGICAL])))); + assert_eq!(from_robj::(&r!("xyz")).is_err(), true); + + // This requires a PR that is not yet merged. + // #[derive(Deserialize, PartialEq, Debug)] + // struct RStrings(Strings); + // assert_eq!(from_robj::(&r!("xyz")), Ok(RStrings(Strings::from_values(["xyz"])))); + // assert_eq!(from_robj::(&r!(["a", "b"])), Ok(RStrings(Strings::from_values(["a", "b"])))); + // assert_eq!(from_robj::(&r!(0)).is_err(), true); } } diff --git a/extendr-api/tests/serde_tests.rs b/extendr-api/tests/serde_tests.rs new file mode 100644 index 0000000000..efd17999ea --- /dev/null +++ b/extendr-api/tests/serde_tests.rs @@ -0,0 +1,86 @@ +#![cfg(feature = "serde")] +use extendr_api::deserializer::from_robj; +use extendr_api::prelude::*; +use extendr_api::serializer::to_robj; +use serde::{Deserialize, Serialize}; + +// Enums are mapped to named lists of lists. +#[derive(Debug, PartialEq, Serialize, Deserialize)] +enum Enum { + Unit, + Newtype(u32), + Tuple(u32, u32), + Struct { a: u32 }, + AnOption(Option), +} + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +struct Test { + int: i32, + // FIXME: something with serialization + // seq: Vec<&'a str>, + option: Option, + option_rint: Option, +} + +/// +#[test] +fn test_back_to_back() -> std::result::Result<(), Box> { + test! { + // region: enum ser-de + + let expected = Enum::Unit; + assert_eq!(expected, from_robj(&to_robj(&expected)?)?); + + let expected = Enum::Newtype(1); + assert_eq!(expected, from_robj(&to_robj(&expected)?)?); + + let expected = Enum::Tuple(1, 2); + assert_eq!(expected, from_robj(&to_robj(&expected)?)?); + + let expected = Enum::Struct { a: 1 }; + assert_eq!(expected, from_robj(&to_robj(&expected)?)?); + + let expected = Enum::AnOption(Some(1)); + assert_eq!(expected, from_robj(&to_robj(&expected)?)?); + + let expected = Enum::AnOption(None); + assert_eq!(expected, from_robj(&to_robj(&expected)?)?); + + // endregion + + // region: struct ser-de + + let test01 = Test { + int: 1, + // seq: vec!["a", "b"], + option: Some(42_i32), + option_rint: Some(Rint::new(21)), + }; + let test02 = Test { + int: 1, + // seq: vec!["a", "b"], + option: None, + option_rint: Some(Rint::na()), + }; + let test03 = Test { + int: 1, + // seq: vec!["a", "b"], + option: None, + option_rint: None, + }; + + let expected = test01; + assert_eq!(expected, from_robj(&to_robj(&expected)?)?); + + let expected = test02; + assert_eq!(expected, from_robj(&to_robj(&expected)?)?); + + let expected = test03; + assert_eq!(expected, from_robj(&to_robj(&expected)?)?); + + // endregion + // Ok(()) + }; + Ok(()) +} diff --git a/extendr-api/tests/serializer_tests.rs b/extendr-api/tests/serializer_tests.rs index cf27d10d33..e86a321697 100644 --- a/extendr-api/tests/serializer_tests.rs +++ b/extendr-api/tests/serializer_tests.rs @@ -1,157 +1,155 @@ -#[cfg(feature = "serde")] -mod test { - use extendr_api::prelude::*; - use extendr_api::serializer::to_robj; - use serde::Serialize; - - #[test] - fn test_serialize_struct() { - test! { - #[derive(Serialize)] - struct Test<'a> { - int: i32, - seq: Vec<&'a str>, - } - - let test = Test { - int: 1, - seq: vec!["a", "b"], - }; - - let expected: Robj = list!(int=1, seq=list!("a", "b")).into(); - assert_eq!(to_robj(&test).unwrap(), expected); +#![cfg(feature = "serde")] +use extendr_api::prelude::*; +use extendr_api::serializer::to_robj; +use serde::Serialize; + +#[test] +fn test_serialize_struct() { + test! { + #[derive(Serialize)] + struct Test<'a> { + int: i32, + seq: Vec<&'a str>, } + + let test = Test { + int: 1, + seq: vec!["a", "b"], + }; + + let expected: Robj = list!(int=1, seq=list!("a", "b")).into(); + assert_eq!(to_robj(&test).unwrap(), expected); } +} - #[test] - fn test_serialize_enum() { - test! { - #[derive(Serialize)] - enum E { - Unit, - Newtype(i32), - Tuple(i32, i32), - Struct { a: i32 }, - } - - let u = E::Unit; - let expected = r!("Unit"); - assert_eq!(to_robj(&u).unwrap(), r!(expected)); - - let n = E::Newtype(1); - let expected = list!(Newtype=1); - assert_eq!(to_robj(&n).unwrap(), r!(expected)); - - let t = E::Tuple(1, 2); - let expected = list!(Tuple=list!(1, 2)); - assert_eq!(to_robj(&t).unwrap(), r!(expected)); - - let s = E::Struct { a: 1 }; - let expected = list!(Struct=list!(a=1)); - assert_eq!(to_robj(&s).unwrap(), r!(expected)); +#[test] +fn test_serialize_enum() { + test! { + #[derive(Serialize)] + enum E { + Unit, + Newtype(i32), + Tuple(i32, i32), + Struct { a: i32 }, } + + let u = E::Unit; + let expected = r!("Unit"); + assert_eq!(to_robj(&u).unwrap(), r!(expected)); + + let n = E::Newtype(1); + let expected = list!(Newtype=1); + assert_eq!(to_robj(&n).unwrap(), r!(expected)); + + let t = E::Tuple(1, 2); + let expected = list!(Tuple=list!(1, 2)); + assert_eq!(to_robj(&t).unwrap(), r!(expected)); + + let s = E::Struct { a: 1 }; + let expected = list!(Struct=list!(a=1)); + assert_eq!(to_robj(&s).unwrap(), r!(expected)); } +} - #[test] - fn test_serialize_robj() { - test! { - #[derive(Serialize)] - struct Null(Robj); - let s = Null(r!(NULL)); - let expected = r!(NULL); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Sym(Symbol); - let s = Sym(sym!(xyz).try_into()?); - let expected = r!("xyz"); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Plist(Pairlist); - let s = Plist(pairlist!(a=1, b=2)); - let expected: Robj = list!(a=1, b=2).into(); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Rstr1(Rstr); - let s = Rstr1(Rstr::from("xyz")); - let expected = r!("xyz"); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Int(Integers); - let s = Int(Integers::from_values([1])); - let expected = r!(1); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Int2(Integers); - let s = Int2(Integers::from_values([1, 2])); - let expected = r!(list![1, 2]); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Dbl2(Doubles); - let s = Dbl2(Doubles::from_values([1.0, 2.0])); - let expected = r!(list![1.0, 2.0]); - assert_eq!(to_robj(&s).unwrap(), expected); - - // BUG! Will probably be fixed by "better-debug" - // - // #[derive(Serialize)] - // struct List1(List); - // let s = List1(list!(a=1, b=2)); - // let expected = r!(list!(a=1, b=2)); - // assert_eq!(to_robj(&s).unwrap(), expected); - - // #[derive(Serialize)] - // struct List2(List); - // let s = List2(list!(1, 2)); - // let expected = r!(list!(1, 2)); - // assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Raw1(Raw); - let s = Raw1(Raw::from_bytes(&[1, 2, 3])); - let expected = r!(Raw::from_bytes(&[1, 2, 3])); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Rint1(Rint); - let s = Rint1(Rint::from(1)); - let expected = r!(1); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Rint2(Rint); - let s = Rint2(Rint::na()); - let expected = r!(()); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Rfloat1(Rfloat); - let s = Rfloat1(Rfloat::from(1.0)); - let expected = r!(1.0); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Rfloat2(Rfloat); - let s = Rfloat2(Rfloat::na()); - let expected = r!(()); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Rbool1(Rbool); - let s = Rbool1(Rbool::from(true)); - let expected = r!(true); - assert_eq!(to_robj(&s).unwrap(), expected); - - #[derive(Serialize)] - struct Rbool2(Rbool); - let s = Rbool2(Rbool::na()); - let expected = r!(()); - assert_eq!(to_robj(&s).unwrap(), expected); - } +#[test] +fn test_serialize_robj() { + test! { + #[derive(Serialize)] + struct Null(Robj); + let s = Null(r!(NULL)); + let expected = r!(NULL); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Sym(Symbol); + let s = Sym(sym!(xyz).try_into()?); + let expected = r!("xyz"); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Plist(Pairlist); + let s = Plist(pairlist!(a=1, b=2)); + let expected: Robj = list!(a=1, b=2).into(); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Rstr1(Rstr); + let s = Rstr1(Rstr::from("xyz")); + let expected = r!("xyz"); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Int(Integers); + let s = Int(Integers::from_values([1])); + let expected = r!(1); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Int2(Integers); + let s = Int2(Integers::from_values([1, 2])); + let expected = r!(list![1, 2]); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Dbl2(Doubles); + let s = Dbl2(Doubles::from_values([1.0, 2.0])); + let expected = r!(list![1.0, 2.0]); + assert_eq!(to_robj(&s).unwrap(), expected); + + // BUG! Will probably be fixed by "better-debug" + // + // #[derive(Serialize)] + // struct List1(List); + // let s = List1(list!(a=1, b=2)); + // let expected = r!(list!(a=1, b=2)); + // assert_eq!(to_robj(&s).unwrap(), expected); + + // #[derive(Serialize)] + // struct List2(List); + // let s = List2(list!(1, 2)); + // let expected = r!(list!(1, 2)); + // assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Raw1(Raw); + let s = Raw1(Raw::from_bytes(&[1, 2, 3])); + let expected = r!(Raw::from_bytes(&[1, 2, 3])); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Rint1(Rint); + let s = Rint1(Rint::from(1)); + let expected = r!(1); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Rint2(Rint); + let s = Rint2(Rint::na()); + let expected = r!(()); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Rfloat1(Rfloat); + let s = Rfloat1(Rfloat::from(1.0)); + let expected = r!(1.0); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Rfloat2(Rfloat); + let s = Rfloat2(Rfloat::na()); + let expected = r!(()); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Rbool1(Rbool); + let s = Rbool1(Rbool::from(true)); + let expected = r!(true); + assert_eq!(to_robj(&s).unwrap(), expected); + + #[derive(Serialize)] + struct Rbool2(Rbool); + let s = Rbool2(Rbool::na()); + let expected = r!(()); + assert_eq!(to_robj(&s).unwrap(), expected); } }