#![cfg_attr(not(feature = "std"), no_std)] #![allow(dead_code)] #[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(Debug, PartialEq)] #[repr(transparent)] struct Wrapped(T); #[derive(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 { 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() { 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() { 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(), ); } } } }