use fromsuper::FromSuper;
use std::collections::HashMap;
use std::rc::Rc;
#[derive(Clone)]
struct Bar {
bar: Option<u32>,
baz: Option<Option<String>>,
}
#[derive(PartialEq, Eq, Debug, FromSuper)]
#[fromsuper(from_type = "crate::Bar", unpack = true)]
struct Foo {
bar: u32,
baz: Option<String>,
}
#[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<T> {
x: Option<Vec<T>>,
}
#[derive(FromSuper)]
#[fromsuper(from_type = "BarGen<T>", unpack = true)]
struct FooGen<T> {
x: Vec<T>,
}
#[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<T, U> {
x: Vec<T>,
#[allow(dead_code)]
y: Vec<U>,
}
#[derive(FromSuper)]
#[fromsuper(from_type = "BarGenMultiNoUnpack<#T,#U>")]
struct FooGenMultiNoUnpack<T> {
x: Vec<T>,
}
#[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<T, U> {
x: Option<Vec<T>>,
#[allow(dead_code)]
y: Vec<U>,
}
#[derive(FromSuper)]
#[fromsuper(from_type = "BarGenMulti<#T,#U>", unpack = true)]
struct FooGenMulti<T> {
x: Vec<T>,
}
#[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<T> {
x: Option<T>,
y: T,
}
#[derive(FromSuper, PartialEq, Debug)]
#[fromsuper(from_type = "BarRenameTest<T>", unpack = true)]
struct FooRenameTest1<T> {
#[fromsuper(rename_from = "x")]
z: T,
}
#[derive(FromSuper, PartialEq, Debug)]
#[fromsuper(from_type = "BarRenameTest<T>")]
struct FooRenameTest2<T> {
#[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<T, U> {
x: Vec<T>,
y: Vec<U>,
}
#[derive(FromSuper)]
#[fromsuper(from_type = "BarGenericsMixed<#T,u32>")]
struct FooGenericsMixed<T> {
x: Vec<T>,
}
#[derive(FromSuper)]
#[fromsuper(from_type = "BarGenericsMixed<#T,u32>")]
struct FooGenericsMixed2 {
y: Vec<u32>,
}
#[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<U, V>,
e: Option<(U, W)>,
}
#[derive(Debug, Clone)]
struct ComplexSub {
x: String,
y: Rc<u64>,
}
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<u8, char>,
}
#[derive(FromSuper)]
#[fromsuper(
from_type = "BarComplex<'a, #T, #U, char, ComplexSub>",
unpack = "true"
)]
#[derive(Debug)]
struct FooComplex3<U> {
#[fromsuper(unpack = false)]
a: u32,
#[fromsuper(unpack = false)]
d: HashMap<U, char>,
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<T> {
a: Option<String>,
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");
}