#![cfg_attr(not(feature = "std"), no_std)] #![allow(dead_code)] // some code is tested for type checking only #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(not(feature = "std"))] use alloc::{ borrow::Cow, borrow::ToOwned, boxed::Box, string::{String, ToString}, }; use core::mem; #[cfg(feature = "std")] use std::borrow::Cow; use derive_more::Into; use static_assertions::assert_not_impl_any; /// Nasty [`mem::transmute()`] that works in generic contexts /// by [`mem::forget`]ing stuff. /// /// It's OK for tests! unsafe fn transmute(from: From) -> To { let to = unsafe { mem::transmute_copy(&from) }; mem::forget(from); to } #[derive(Clone, Copy, Debug, PartialEq)] #[repr(transparent)] struct Wrapped(T); #[derive(Clone, Copy, Debug, PartialEq)] #[repr(transparent)] struct Transmuted(T); impl From> for Transmuted { fn from(from: Wrapped) -> Self { // SAFETY: repr(transparent) unsafe { transmute(from) } } } impl From<&Wrapped> for &Transmuted { fn from(from: &Wrapped) -> Self { // SAFETY: repr(transparent) unsafe { transmute(from) } } } impl From<&mut Wrapped> for &mut Transmuted { fn from(from: &mut Wrapped) -> Self { // SAFETY: repr(transparent) unsafe { transmute(from) } } } mod unit { #![allow(clippy::unit_cmp)] // because of type inference in assertions use super::*; #[derive(Debug, Into, PartialEq)] struct Unit; #[derive(Debug, Into, PartialEq)] struct Tuple(); #[derive(Debug, Into, PartialEq)] struct Struct {} #[test] fn assert() { assert_eq!((), Unit.into()); assert_eq!((), Tuple().into()); assert_eq!((), Struct {}.into()); } mod generic { use super::*; #[derive(Debug, Into, PartialEq)] struct Unit; #[derive(Debug, Into, PartialEq)] struct Tuple(); #[derive(Debug, Into, PartialEq)] struct Struct {} #[test] fn assert() { assert_eq!((), Unit::<1>.into()); assert_eq!((), Tuple::<1>().into()); assert_eq!((), Struct::<1> {}.into()); } } } mod single_field { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(i32); #[derive(Debug, Into, PartialEq)] struct Struct { field: i32, } #[test] fn assert() { assert_eq!(42, Tuple(42).into()); assert_eq!(42, Struct { field: 42 }.into()); } mod skip { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(#[into(skip)] i32); #[derive(Debug, Into, PartialEq)] struct Struct { #[into(skip)] field: i32, } #[test] fn assert() { #![allow(clippy::unit_cmp)] // because of type inference in assertions assert_eq!((), Tuple(42).into()); assert_eq!((), Struct { field: 42 }.into()); } } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(i64)] #[into(i128)] struct Tuple(i32); #[derive(Debug, Into, PartialEq)] #[into(Box, Cow<'_, str>)] struct Struct { field: String, } #[test] fn assert() { assert_not_impl_any!(Tuple: Into); assert_not_impl_any!(Struct: Into); assert_eq!(42_i64, Tuple(42).into()); assert_eq!(42_i128, Tuple(42).into()); assert_eq!( Box::::from("42".to_owned()), Struct { field: "42".to_string(), } .into(), ); assert_eq!( Cow::Borrowed("42"), Cow::::from(Struct { field: "42".to_string(), }), ); } mod ref_ { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref)] struct Unnamed(i32); #[derive(Debug, Into, PartialEq)] #[into(ref)] struct Named { field: i32, } #[test] fn assert() { assert_eq!(&42, <&i32>::from(&Unnamed(42))); assert_eq!(&42, <&i32>::from(&Named { field: 42 })); } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref(i32, Unnamed))] struct Tuple(Unnamed); #[derive(Debug, Into, PartialEq)] #[into(ref(i32, Named))] struct Struct { field: Named, } #[test] fn assert() { assert_eq!(&42, <&i32>::from(&Tuple(Unnamed(42)))); assert_eq!(&Unnamed(42), <&Unnamed>::from(&Tuple(Unnamed(42)))); assert_eq!( &42, <&i32>::from(&Struct { field: Named { field: 42 }, }), ); assert_eq!( &Named { field: 42 }, <&Named>::from(&Struct { field: Named { field: 42 }, }), ); } } } mod ref_mut { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref_mut)] struct Unnamed(i32); #[derive(Debug, Into, PartialEq)] #[into(ref_mut)] struct Named { field: i32, } #[test] fn assert() { assert_eq!(&mut 42, <&mut i32>::from(&mut Unnamed(42))); assert_eq!(&mut 42, <&mut i32>::from(&mut Named { field: 42 })); } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref_mut(i32, Unnamed))] struct Tuple(Unnamed); #[derive(Debug, Into, PartialEq)] #[into(ref_mut(i32, Named))] struct Struct { field: Named, } #[test] fn assert() { assert_eq!(&mut 42, <&mut i32>::from(&mut Tuple(Unnamed(42)))); assert_eq!( &mut Unnamed(42), <&mut Unnamed>::from(&mut Tuple(Unnamed(42))), ); assert_eq!( &mut 42, <&mut i32>::from(&mut Struct { field: Named { field: 42 }, }), ); assert_eq!( &mut Named { field: 42 }, <&mut Named>::from(&mut Struct { field: Named { field: 42 }, }), ); } } } } mod generic { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(Wrapped); #[derive(Debug, Into, PartialEq)] struct Struct { field: Wrapped, } #[test] fn assert() { assert_eq!(Wrapped(42), Tuple(Wrapped(42)).into()); assert_eq!(Wrapped(42), Struct { field: Wrapped(42) }.into()); } mod skip { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(#[into(skip)] Wrapped); #[derive(Debug, Into, PartialEq)] struct Struct { #[into(skip)] field: Wrapped, } #[test] fn assert() { #![allow(clippy::unit_cmp)] // because of type inference in assertions assert_eq!((), Tuple(Wrapped(42)).into()); assert_eq!((), Struct { field: Wrapped(42) }.into()); } } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(Transmuted)] struct Tuple(Wrapped); #[derive(Debug, Into, PartialEq)] #[into(Transmuted)] struct Struct { field: Wrapped, } #[test] fn assert() { assert_eq!(Transmuted(42), Tuple(Wrapped(42)).into()); assert_eq!(Transmuted(42), Struct { field: Wrapped(42) }.into()); } } mod ref_ { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref)] struct Tuple(Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref)] struct Struct { field: Wrapped, } #[test] fn assert() { assert_eq!(&Wrapped(42), <&Wrapped<_>>::from(&Tuple(Wrapped(42)))); assert_eq!( &Wrapped(42), <&Wrapped<_>>::from(&Struct { field: Wrapped(42) }) ); } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref(Transmuted))] struct Tuple(Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref(Transmuted))] struct Struct { field: Wrapped, } #[test] fn assert() { assert_eq!( &Transmuted(42), <&Transmuted<_>>::from(&Tuple(Wrapped(42))), ); assert_eq!( &Transmuted(42), <&Transmuted<_>>::from(&Struct { field: Wrapped(42) }), ); } } } mod ref_mut { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref_mut)] struct Tuple(Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref_mut)] struct Struct { field: Wrapped, } #[test] fn assert() { assert_eq!( &mut Wrapped(42), <&mut Wrapped<_>>::from(&mut Tuple(Wrapped(42))) ); assert_eq!( &mut Wrapped(42), <&mut Wrapped<_>>::from(&mut Struct { field: Wrapped(42) }), ); } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref_mut(Transmuted))] struct Tuple(Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref_mut(Transmuted))] struct Struct { field: Wrapped, } #[test] fn assert() { assert_eq!( &mut Transmuted(42), <&mut Transmuted<_>>::from(&mut Tuple(Wrapped(42))), ); assert_eq!( &mut Transmuted(42), <&mut Transmuted<_>>::from(&mut Struct { field: Wrapped(42) }), ); } } } mod indirect { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(&'static Wrapped); #[derive(Debug, Into, PartialEq)] struct Struct { field: &'static Wrapped, } #[test] fn assert() { assert_eq!(&Wrapped(42), <&Wrapped<_>>::from(Tuple(&Wrapped(42)))); assert_eq!( &Wrapped(42), <&Wrapped<_>>::from(Struct { field: &Wrapped(42), }), ); } } mod bounded { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(Wrapped); #[derive(Debug, Into, PartialEq)] struct Struct { field: Wrapped, } #[test] fn assert() { assert_eq!(Wrapped(42), Tuple(Wrapped(42)).into()); assert_eq!(Wrapped(42), Struct { field: Wrapped(42) }.into()); } } mod r#const { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(Wrapped); #[derive(Debug, Into, PartialEq)] struct Struct { field: Wrapped, } #[test] fn assert() { assert_eq!(Wrapped(1), Tuple::<1, _>(Wrapped(1)).into()); assert_eq!(Wrapped(1), Struct::<_, 1> { field: Wrapped(1) }.into()); } } } } mod multi_field { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(i32, i64); #[derive(Debug, Into, PartialEq)] struct Struct { field1: i32, field2: i64, } #[test] fn assert() { assert_eq!((1, 2_i64), Tuple(1, 2_i64).into()); assert_eq!( (1, 2_i64), Struct { field1: 1, field2: 2_i64, } .into(), ); } mod skip { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(i32, #[into(skip)] i64); #[derive(Debug, Into, PartialEq)] struct Struct { #[into(skip)] field1: i32, field2: i64, } #[test] fn assert() { assert_eq!(1, Tuple(1, 2_i64).into()); assert_eq!( 2_i64, Struct { field1: 1, field2: 2_i64, } .into(), ); } } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into((i32, i64))] #[into((i64, i128))] struct Tuple(i16, i32); #[derive(Debug, Into, PartialEq)] #[into((Box, i32), (Cow<'_, str>, i64))] struct Struct { field1: String, field2: i32, } #[test] fn assert() { assert_not_impl_any!(Tuple: Into<(i16, i32)>); assert_not_impl_any!(Struct: Into<(String, i32)>); assert_eq!((1, 2_i64), Tuple(1_i16, 2).into()); assert_eq!((1_i64, 2_i128), Tuple(1_i16, 2).into()); assert_eq!( (Box::::from("42".to_owned()), 1), Struct { field1: "42".to_string(), field2: 1, } .into(), ); assert_eq!( (Cow::Borrowed("42"), 1_i64), Struct { field1: "42".to_string(), field2: 1, } .into(), ); } mod ref_ { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref)] struct Unnamed(i32, i64); #[derive(Debug, Into, PartialEq)] #[into(ref)] struct Named { field1: i32, field2: i64, } #[test] fn assert() { assert_eq!((&1, &2_i64), (&Unnamed(1, 2_i64)).into()); assert_eq!( (&1, &2_i64), (&Named { field1: 1, field2: 2_i64, }) .into(), ); } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref( (Transmuted, Transmuted), (Transmuted, Wrapped)), )] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref( (Transmuted, Transmuted), (Transmuted, Wrapped)), )] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (&Transmuted(1), &Transmuted(2_i64)), (&Tuple(Wrapped(1), Wrapped(2_i64))).into(), ); assert_eq!( (&Transmuted(1), &Wrapped(2_i64)), (&Tuple(Wrapped(1), Wrapped(2_i64))).into(), ); assert_eq!( (&Transmuted(1), &Transmuted(2_i64)), (&Struct { field1: Wrapped(1), field2: Wrapped(2_i64), }) .into(), ); assert_eq!( (&Transmuted(1), &Wrapped(2_i64)), (&Struct { field1: Wrapped(1), field2: Wrapped(2_i64), }) .into(), ); } } } mod ref_mut { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref_mut)] struct Unnamed(i32, i64); #[derive(Debug, Into, PartialEq)] #[into(ref_mut)] struct Named { field1: i32, field2: i64, } #[test] fn assert() { assert_eq!((&mut 1, &mut 2_i64), (&mut Unnamed(1, 2_i64)).into()); assert_eq!( (&mut 1, &mut 2_i64), (&mut Named { field1: 1, field2: 2_i64, }) .into(), ); } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref_mut( (Transmuted, Transmuted), (Transmuted, Wrapped)), )] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref_mut( (Transmuted, Transmuted), (Transmuted, Wrapped)), )] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (&mut Transmuted(1), &mut Transmuted(2_i64)), (&mut Tuple(Wrapped(1), Wrapped(2_i64))).into(), ); assert_eq!( (&mut Transmuted(1), &mut Wrapped(2_i64)), (&mut Tuple(Wrapped(1), Wrapped(2_i64))).into(), ); assert_eq!( (&mut Transmuted(1), &mut Transmuted(2_i64)), (&mut Struct { field1: Wrapped(1), field2: Wrapped(2_i64), }) .into(), ); assert_eq!( (&mut Transmuted(1), &mut Wrapped(2_i64)), (&mut Struct { field1: Wrapped(1), field2: Wrapped(2_i64), }) .into(), ); } } } } mod generic { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (Wrapped(1), Wrapped(2)), Tuple(Wrapped(1), Wrapped(2)).into(), ); assert_eq!( (Wrapped(1), Wrapped(2)), Struct { field1: Wrapped(1), field2: Wrapped(2), } .into(), ); } mod skip { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(Wrapped, #[into(skip)] Wrapped); #[derive(Debug, Into, PartialEq)] struct Struct { #[into(skip)] field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!(Wrapped(1), Tuple(Wrapped(1), Wrapped(2)).into()); assert_eq!( Wrapped(2), Struct { field1: Wrapped(1), field2: Wrapped(2), } .into(), ); } } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into((Transmuted, Transmuted))] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] #[into((Transmuted, Transmuted))] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (Transmuted(1), Transmuted(2)), Tuple(Wrapped(1), Wrapped(2)).into(), ); assert_eq!( (Transmuted(1), Transmuted(2)), Struct { field1: Wrapped(1), field2: Wrapped(2), } .into(), ); } } mod ref_ { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref)] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref)] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (&Wrapped(1), &Wrapped(2)), (&Tuple(Wrapped(1), Wrapped(2))).into(), ); assert_eq!( (&Wrapped(1), &Wrapped(2)), (&Struct { field1: Wrapped(1), field2: Wrapped(2), }) .into(), ); } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref((Transmuted, Transmuted)))] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref((Transmuted, Transmuted)))] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (&Transmuted(1), &Transmuted(2)), (&Tuple(Wrapped(1), Wrapped(2))).into(), ); assert_eq!( (&Transmuted(1), &Transmuted(2)), (&Struct { field1: Wrapped(1), field2: Wrapped(2), }) .into(), ); } } } mod ref_mut { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref_mut)] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref_mut)] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (&mut Wrapped(1), &mut Wrapped(2)), (&mut Tuple(Wrapped(1), Wrapped(2))).into(), ); assert_eq!( (&mut Wrapped(1), &mut Wrapped(2)), (&mut Struct { field1: Wrapped(1), field2: Wrapped(2), }) .into(), ); } mod types { use super::*; #[derive(Debug, Into, PartialEq)] #[into(ref_mut((Transmuted, Transmuted)))] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] #[into(ref_mut((Transmuted, Transmuted)))] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (&mut Transmuted(1), &mut Transmuted(2)), (&mut Tuple(Wrapped(1), Wrapped(2))).into(), ); assert_eq!( (&mut Transmuted(1), &mut Transmuted(2)), (&mut Struct { field1: Wrapped(1), field2: Wrapped(2), }) .into(), ); } } } mod indirect { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple( &'static Wrapped, &'static Wrapped, ); #[derive(Debug, Into, PartialEq)] struct Struct { field1: &'static Wrapped, field2: &'static Wrapped, } #[test] fn assert() { assert_eq!( (&Wrapped(1), &Wrapped(2)), Tuple(&Wrapped(1), &Wrapped(2)).into(), ); assert_eq!( (&Wrapped(1), &Wrapped(2)), (Struct { field1: &Wrapped(1), field2: &Wrapped(2), }) .into(), ); } } mod bounded { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (Wrapped(1), Wrapped(2)), Tuple(Wrapped(1), Wrapped(2)).into(), ); assert_eq!( (Wrapped(1), Wrapped(2)), Struct { field1: Wrapped(1), field2: Wrapped(2), } .into(), ); } } mod r#const { use super::*; #[derive(Debug, Into, PartialEq)] struct Tuple(Wrapped, Wrapped); #[derive(Debug, Into, PartialEq)] struct Struct { field1: Wrapped, field2: Wrapped, } #[test] fn assert() { assert_eq!( (Wrapped(1), Wrapped(2)), Tuple::<1, _, _>(Wrapped(1), Wrapped(2)).into(), ); assert_eq!( (Wrapped(1), Wrapped(2)), Struct::<_, 1, _> { field1: Wrapped(1), field2: Wrapped(2), } .into(), ); } } } } mod with_fields { use super::*; mod only { use super::*; #[derive(Clone, Copy, Debug, Into)] struct Tuple(#[into] i32, f64, #[into] f64); // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl From for (i32, f64, f64) { fn from(value: Tuple) -> Self { (value.0, value.1, value.2) } } // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl From for (i32, f64) { fn from(value: Tuple) -> Self { (value.0, value.2) } } #[test] fn tuple() { let t = Tuple(1, 2.0, 3.0); assert_eq!(1, t.into()); assert_eq!(3.0, t.into()); } #[derive(Clone, Copy, Debug, Into)] struct Struct { #[into] a: i32, b: f64, #[into] c: f64, } // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl From for (i32, f64, f64) { fn from(value: Struct) -> Self { (value.a, value.b, value.c) } } // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl From for (i32, f64) { fn from(value: Struct) -> Self { (value.a, value.c) } } #[test] fn named() { let s = Struct { a: 1, b: 2.0, c: 3.0, }; assert_eq!(1, s.into()); assert_eq!(3.0, s.into()); } mod types { use super::*; #[derive(Clone, Debug, Into)] struct Tuple( #[into(Box, Cow<'_, str>)] String, f64, #[into(f32, f64)] f32, ); // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl From for String { fn from(value: Tuple) -> Self { value.0 } } // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl From for (String, f64, f32) { fn from(value: Tuple) -> Self { (value.0, value.1, value.2) } } #[test] fn tuple() { let f = Tuple("1".to_owned(), 2.0, 3.0); assert_eq!(Box::::from("1".to_owned()), f.clone().into()); assert_eq!(Cow::Borrowed("1"), Cow::::from(f.clone())); assert_eq!(3.0f32, f.clone().into()); assert_eq!(3.0f64, f.into()); } #[derive(Clone, Debug, Into)] struct Struct { #[into(Box, Cow<'_, str>)] a: String, b: f64, #[into(f32, f64)] c: f32, } // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl From for String { fn from(value: Struct) -> Self { value.a } } // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl From for (String, f64, f32) { fn from(value: Struct) -> Self { (value.a, value.b, value.c) } } // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl From for (Box, f32) { fn from(value: Struct) -> Self { (value.a.into(), value.c) } } #[test] fn named() { let s = Struct { a: "1".to_owned(), b: 2.0, c: 3.0, }; assert_eq!(Box::::from("1".to_owned()), s.clone().into()); assert_eq!(Cow::Borrowed("1"), Cow::::from(s.clone())); assert_eq!(3.0f32, s.clone().into()); assert_eq!(3.0f64, s.into()); } mod r#ref { use super::*; #[derive(Debug, Into)] struct Tuple(#[into(ref)] String, f64, #[into(ref)] f64); // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl<'a> From<&'a Tuple> for (&'a String, &'a f64, &'a f64) { fn from(value: &'a Tuple) -> Self { (&value.0, &value.1, &value.2) } } #[test] fn tuple() { let t = Tuple("1".to_owned(), 2.0, 3.0); assert_eq!(&"1".to_owned(), <&String>::from(&t)); assert_eq!(&3.0, <&f64>::from(&t)); } #[derive(Debug, Into)] struct Struct { #[into(ref)] a: String, b: f64, #[into(ref)] c: f64, } // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl<'a> From<&'a Struct> for (&'a String, &'a f64, &'a f64) { fn from(value: &'a Struct) -> Self { (&value.a, &value.b, &value.c) } } // Asserts that macro expansion doesn't generate this impl, by producing a trait // implementations conflict error during compilation, if it does. impl<'a> From<&'a Struct> for (&'a String, &'a f64) { fn from(value: &'a Struct) -> Self { (&value.a, &value.c) } } #[test] fn named() { let s = Struct { a: "1".to_owned(), b: 2.0, c: 3.0, }; assert_eq!(&"1".to_owned(), <&String>::from(&s)); assert_eq!(&3.0, <&f64>::from(&s)); } mod types { use super::*; #[derive(Debug, Into)] struct Tuple( #[into(ref(Transmuted))] Wrapped, #[into(ref(Wrapped))] Wrapped, ); #[test] fn tuple() { let t = Tuple(Wrapped(1), Wrapped(2)); assert_eq!(&Transmuted(1), <&Transmuted>::from(&t)); assert_eq!(&Wrapped(2), <&Wrapped>::from(&t)); } #[derive(Debug, Into)] struct Struct { #[into(ref(Transmuted))] a: Wrapped, #[into(ref(Wrapped))] b: Wrapped, } #[test] fn named() { let s = Struct { a: Wrapped(1), b: Wrapped(2), }; assert_eq!(&Transmuted(1), <&Transmuted>::from(&s)); assert_eq!(&Wrapped(2), <&Wrapped>::from(&s)); } } mod ref_mut { use super::*; #[derive(Debug, Into)] struct Tuple(#[into(ref_mut)] i32, f64, #[into(ref_mut)] f64); #[test] fn tuple() { let mut t = Tuple(1, 2.0, 3.0); assert_eq!(&mut 1, <&mut i32>::from(&mut t)); assert_eq!(&mut 3.0, <&mut f64>::from(&mut t)); } #[derive(Debug, Into)] struct Struct { #[into(ref_mut)] a: i32, b: f64, #[into(ref_mut)] c: f64, } #[test] fn named() { let mut s = Struct { a: 1, b: 2.0, c: 3.0, }; assert_eq!(&mut 1, <&mut i32>::from(&mut s)); assert_eq!(&mut 3.0, <&mut f64>::from(&mut s)); } mod types { use super::*; #[derive(Debug, Into)] struct Tuple( #[into(ref_mut(Transmuted))] Wrapped, #[into(ref_mut(Wrapped))] Wrapped, ); #[test] fn tuple() { let mut t = Tuple(Wrapped(1), Wrapped(2)); assert_eq!( &mut Transmuted(1), <&mut Transmuted>::from(&mut t), ); assert_eq!( &mut Wrapped(2), <&mut Wrapped>::from(&mut t), ); } #[derive(Debug, Into)] struct Struct { #[into(ref_mut(Transmuted))] a: Wrapped, #[into(ref_mut(Wrapped))] b: Wrapped, } #[test] fn named() { let mut s = Struct { a: Wrapped(1), b: Wrapped(2), }; assert_eq!( &mut Transmuted(1), <&mut Transmuted>::from(&mut s), ); assert_eq!( &mut Wrapped(2), <&mut Wrapped>::from(&mut s), ); } } } } } } mod mixed { use super::*; #[derive(Debug, Into)] #[into(ref((Wrapped, Transmuted)))] struct Tuple( #[into(owned, ref(Transmuted))] Wrapped, #[into(skip)] #[into(ref)] Wrapped, #[into(ref_mut(Wrapped, Transmuted))] Wrapped, ); #[test] fn tuple() { let mut t = Tuple(Wrapped(1), Wrapped(2.0), Wrapped(3.0)); assert_eq!(&Transmuted(1), <&Transmuted>::from(&t)); assert_eq!(&mut Transmuted(3.0), <&mut Transmuted>::from(&mut t)); assert_eq!(&mut Wrapped(3.0), <&mut Wrapped>::from(&mut t)); assert_eq!((&Wrapped(1), &Transmuted(3.0)), (&t).into()); assert_eq!(&Wrapped(2.0), <&Wrapped>::from(&t)); assert_eq!(Wrapped(1), t.into()); } #[derive(Debug, Into)] #[into(ref((Wrapped, Transmuted)))] struct Struct { #[into(owned, ref(Transmuted))] a: Wrapped, #[into(skip)] #[into(ref)] b: Wrapped, #[into(ref_mut(Wrapped, Transmuted))] c: Wrapped, } #[test] fn named() { let mut s = Struct { a: Wrapped(1), b: Wrapped(2.0), c: Wrapped(3.0), }; assert_eq!(&Transmuted(1), <&Transmuted>::from(&s)); assert_eq!(&mut Transmuted(3.0), <&mut Transmuted>::from(&mut s)); assert_eq!(&mut Wrapped(3.0), <&mut Wrapped>::from(&mut s)); assert_eq!((&Wrapped(1), &Transmuted(3.0)), (&s).into()); assert_eq!(&Wrapped(2.0), <&Wrapped>::from(&s)); assert_eq!(Wrapped(1), s.into()); } mod separate { use super::*; #[derive(Clone, Copy, Debug, Into)] #[into(ref)] #[into(owned)] #[into((Wrapped, Transmuted))] #[into(ref_mut((Wrapped, Transmuted)))] struct Tuple( #[into(ref)] #[into(ref(Transmuted))] #[into] Wrapped, #[into(ref_mut)] #[into(ref_mut(Transmuted))] #[into(owned)] Wrapped, ); #[test] fn tuple() { let mut t = Tuple(Wrapped(1), Wrapped(2.0)); assert_eq!((&Wrapped(1), &Wrapped(2.0)), (&t).into()); assert_eq!((Wrapped(1), Wrapped(2.0)), t.into()); assert_eq!((Wrapped(1), Transmuted(2.0)), t.into()); assert_eq!((&mut Wrapped(1), &mut Transmuted(2.0)), (&mut t).into()); assert_eq!(&Wrapped(1), <&Wrapped>::from(&t)); assert_eq!(&Transmuted(1), <&Transmuted>::from(&t)); assert_eq!(Wrapped(1), >::from(t)); assert_eq!(&mut Wrapped(2.0), <&mut Wrapped>::from(&mut t)); assert_eq!(&mut Transmuted(2.0), <&mut Transmuted>::from(&mut t)); assert_eq!(Wrapped(2.0), >::from(t)); } #[derive(Clone, Copy, Debug, Into)] #[into(ref)] #[into(owned)] #[into((Wrapped, Transmuted))] #[into(ref_mut((Wrapped, Transmuted)))] struct Struct { #[into(ref)] #[into(ref (Transmuted < i32 >))] #[into] a: Wrapped, #[into(ref_mut)] #[into(ref_mut(Transmuted < f32 >))] #[into(owned)] b: Wrapped, } #[test] fn named() { let mut s = Struct { a: Wrapped(1), b: Wrapped(2.0), }; assert_eq!((&Wrapped(1), &Wrapped(2.0)), (&s).into()); assert_eq!((Wrapped(1), Wrapped(2.0)), s.into()); assert_eq!((Wrapped(1), Transmuted(2.0)), s.into()); assert_eq!((&mut Wrapped(1), &mut Transmuted(2.0)), (&mut s).into()); assert_eq!(&Wrapped(1), <&Wrapped>::from(&s)); assert_eq!(&Transmuted(1), <&Transmuted>::from(&s)); assert_eq!(Wrapped(1), >::from(s)); assert_eq!(&mut Wrapped(2.0), <&mut Wrapped>::from(&mut s)); assert_eq!(&mut Transmuted(2.0), <&mut Transmuted>::from(&mut s),); assert_eq!(Wrapped(2.0), >::from(s)); } } } }