use fromsuper::FromSuper; use std::collections::HashMap; use std::rc::Rc; #[derive(Clone)] struct Bar { bar: Option, baz: Option>, } #[derive(PartialEq, Eq, Debug, FromSuper)] #[fromsuper(from_type = "crate::Bar", unpack = true)] struct Foo { bar: u32, baz: Option, } #[test] fn basic_unwrap() { assert_eq!( Foo { bar: 42, baz: None }, Foo::try_from(Bar { bar: Some(42), baz: Some(None), }) .unwrap() ); assert!(Foo::try_from(Bar { bar: Some(42), baz: None, }) .is_err()); } #[test] fn basic_try_unwrap() { assert!(Foo::try_from(Bar { bar: Some(42), baz: None, }) .is_err()); assert!(Foo::try_from(Bar { bar: Some(42), baz: Some(None), }) .is_ok()); } struct BarGen { x: Option>, } #[derive(FromSuper)] #[fromsuper(from_type = "BarGen", unpack = true)] struct FooGen { x: Vec, } #[test] fn test_generics_single() { let bar = BarGen { x: Some(vec!["abc"]), }; let foo = FooGen::try_from(bar).unwrap(); assert_eq!(foo.x[0], "abc") } struct BarGenMultiNoUnpack { x: Vec, #[allow(dead_code)] y: Vec, } #[derive(FromSuper)] #[fromsuper(from_type = "BarGenMultiNoUnpack<#T,#U>")] struct FooGenMultiNoUnpack { x: Vec, } #[test] fn test_generics_multi_no_unpack() { let bar = BarGenMultiNoUnpack { x: vec!["abc"], y: vec![42], }; let foo: FooGenMultiNoUnpack<_> = bar.into(); assert_eq!(foo.x[0], "abc") } struct BarGenMulti { x: Option>, #[allow(dead_code)] y: Vec, } #[derive(FromSuper)] #[fromsuper(from_type = "BarGenMulti<#T,#U>", unpack = true)] struct FooGenMulti { x: Vec, } #[test] fn test_generics_multi() { let bar = BarGenMulti { x: Some(vec!["abc"]), y: vec![42], }; let foo = FooGenMulti::try_from(bar).unwrap(); assert_eq!(foo.x[0], "abc") } #[derive(PartialEq, Debug)] struct BarRenameTest { x: Option, y: T, } #[derive(FromSuper, PartialEq, Debug)] #[fromsuper(from_type = "BarRenameTest", unpack = true)] struct FooRenameTest1 { #[fromsuper(rename_from = "x")] z: T, } #[derive(FromSuper, PartialEq, Debug)] #[fromsuper(from_type = "BarRenameTest")] struct FooRenameTest2 { #[fromsuper(rename_from = "y")] z: T, } #[test] fn test_rename_from() { assert_eq!( FooRenameTest1 { z: 42 }, BarRenameTest { x: Some(42), y: 53 }.try_into().unwrap() ); assert_eq!( FooRenameTest2 { z: 53 }, BarRenameTest { x: Some(42), y: 53 }.into() ); } #[derive(Debug, Clone)] struct BarGenericsMixed { x: Vec, y: Vec, } #[derive(FromSuper)] #[fromsuper(from_type = "BarGenericsMixed<#T,u32>")] struct FooGenericsMixed { x: Vec, } #[derive(FromSuper)] #[fromsuper(from_type = "BarGenericsMixed<#T,u32>")] struct FooGenericsMixed2 { y: Vec, } #[test] fn test_generics_mixed_free_and_specific() { let bar = BarGenericsMixed { x: vec!["huhu"], y: vec![42], }; let foo: FooGenericsMixed<_> = bar.clone().into(); assert_eq!(foo.x[0], "huhu"); let foo: FooGenericsMixed2 = bar.into(); assert_eq!(foo.y[0], 42); } #[derive(Debug, Clone)] struct BarLifetime1<'a> { x: u32, y: &'a str, } #[derive(FromSuper)] #[fromsuper(from_type = "BarLifetime1<'a>")] struct FooLifetime1<'a> { y: &'a str, } #[derive(FromSuper)] #[fromsuper(from_type = "BarLifetime1<'static>")] struct FooLifetime2 { x: u32, } #[test] fn test_lifetime() { let s = format!("Test {}", 123); let bar1 = BarLifetime1 { x: 42, y: &s[2..] }; let bar2 = BarLifetime1 { x: 53, y: "hello" }; let foo: FooLifetime1 = bar1.clone().into(); assert_eq!(&s[2..], foo.y); let foo: FooLifetime2 = bar2.clone().into(); assert_eq!(53, foo.x); } #[derive(Debug, Clone)] struct BarComplex<'a, T: 'static, U, V, W> { a: u32, b: Option<&'a str>, c: Option<&'static T>, d: HashMap, e: Option<(U, W)>, } #[derive(Debug, Clone)] struct ComplexSub { x: String, y: Rc, } static COMPLEX_C: i16 = -42; #[derive(FromSuper)] #[fromsuper(from_type = "BarComplex<'a, #T, #U, #V, #W>")] struct FooComplex1 {} #[derive(FromSuper)] #[fromsuper(from_type = "BarComplex<'a, #T, u8, char, #W>", unpack = "true")] struct FooComplex2<'a, T: 'static> { b: &'a str, c: &'static T, #[fromsuper(unpack = false)] d: HashMap, } #[derive(FromSuper)] #[fromsuper( from_type = "BarComplex<'a, #T, #U, char, ComplexSub>", unpack = "true" )] #[derive(Debug)] struct FooComplex3 { #[fromsuper(unpack = false)] a: u32, #[fromsuper(unpack = false)] d: HashMap, e: (U, ComplexSub), } #[test] fn test_complex() { let s = format!("Test {}", 123); let bar = BarComplex { a: 42, b: Some(&s[2..]), c: Some(&COMPLEX_C), d: ([(1u8, 'a'), (2, 'b')]).into_iter().collect(), e: Some(( 16u8, ComplexSub { x: "hi there".to_string(), y: Rc::new(1_000_000_000_000), }, )), }; let _: FooComplex1 = bar.clone().into(); let foo: FooComplex2<_> = bar.clone().try_into().unwrap(); assert_eq!(foo.b, "st 123"); assert_eq!(*foo.c, -42); assert_eq!(foo.d[&2], 'b'); let foo: FooComplex3<_> = bar.clone().try_into().unwrap(); assert_eq!(foo.a, 42); assert_eq!(foo.d[&2], 'b'); assert_eq!(foo.e.0, 16); assert_eq!(foo.e.1.x, "hi there"); assert_eq!(*foo.e.1.y, 1_000_000_000_000); } #[derive(Debug)] struct BarRef { a: Option, b: String, #[allow(dead_code)] c: T, } #[derive(Debug, FromSuper)] #[fromsuper(from_type = "&'a BarRef<#T>", unpack = true, make_refs = true)] struct FooRef1<'a> { a: &'a String, #[fromsuper(unpack = false)] b: &'a String, } #[test] fn test_ref() { let bar = BarRef { a: Some("hello".to_string()), b: "world".to_string(), c: 42, }; let barref = &bar; let foo: FooRef1 = barref.try_into().unwrap(); assert_eq!(foo.a, "hello"); assert_eq!(foo.b, "world"); } #[derive(Debug)] struct BarDefault { a: Option>, #[allow(dead_code)] b: Option, } #[derive(Debug, FromSuper)] #[fromsuper(from_type = "BarDefault", unpack = true)] struct FooDefault { #[fromsuper(unpack_or_default = true)] a: Vec, // #[fromsuper(unpack_or_default = true)] // b: std::fs::File, } #[test] fn test_default() { let bar1 = BarDefault { a: Some(vec![1]), b: None, }; let foo1: FooDefault = bar1.try_into().unwrap(); assert_eq!(foo1.a, vec![1]); let bar2 = BarDefault { a: None, b: None }; let foo2: FooDefault = bar2.try_into().unwrap(); assert_eq!(foo2.a, vec![]); }