#![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::ToOwned, collections::VecDeque, string::String, vec, vec::Vec}; #[cfg(feature = "std")] use std::collections::VecDeque; use core::ptr; use derive_more::AsRef; struct Helper(i32, f64, bool); impl AsRef for Helper { fn as_ref(&self) -> &i32 { &self.0 } } impl AsRef for Helper { fn as_ref(&self) -> &f64 { &self.1 } } impl AsRef for Helper { fn as_ref(&self) -> &bool { &self.2 } } struct LifetimeHelper<'a>(&'a i32); impl AsRef for LifetimeHelper<'static> { fn as_ref(&self) -> &i32 { self.0 } } struct ConstParamHelper([i32; N]); impl AsRef<[i32]> for ConstParamHelper<0> { fn as_ref(&self) -> &[i32] { self.0.as_ref() } } mod single_field { use super::*; mod tuple { use super::*; #[derive(AsRef)] struct Nothing(String); #[test] fn nothing() { let item = Nothing("test".to_owned()); assert!(ptr::eq(item.as_ref(), &item.0)); } #[derive(AsRef)] #[as_ref(forward)] struct Forward(String); #[test] fn forward() { let item = Forward("test".to_owned()); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } #[derive(AsRef)] struct Field(#[as_ref] String); #[test] fn field() { let item = Field("test".to_owned()); assert!(ptr::eq(item.as_ref(), &item.0)); } #[derive(AsRef)] struct FieldForward(#[as_ref(forward)] String); #[test] fn field_forward() { let item = FieldForward("test".to_owned()); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } #[derive(AsRef)] #[as_ref(i32, f64)] struct Types(Helper); // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for Types { fn as_ref(&self) -> &bool { self.0.as_ref() } } // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, by // producing a trait implementations conflict error during compilation, if it does. impl AsRef for Types { fn as_ref(&self) -> &Helper { &self.0 } } #[test] fn types() { let item = Types(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &f64 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } #[derive(AsRef)] #[as_ref(i32, Helper)] struct TypesWithInner(Helper); // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for TypesWithInner { fn as_ref(&self) -> &bool { self.0.as_ref() } } #[test] fn types_with_inner() { let item = TypesWithInner(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &Helper = item.as_ref(); assert!(ptr::eq(rf, &item.0)); } type RenamedFoo = Helper; #[derive(AsRef)] #[as_ref(i32, RenamedFoo)] struct TypesWithRenamedInner(Helper); // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for TypesWithRenamedInner { fn as_ref(&self) -> &bool { self.0.as_ref() } } #[test] fn types_with_renamed_inner() { let item = TypesWithRenamedInner(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &Helper = item.as_ref(); assert!(ptr::eq(rf, &item.0)); } #[derive(AsRef)] struct FieldTypes(#[as_ref(i32, f64)] Helper); // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for FieldTypes { fn as_ref(&self) -> &bool { self.0.as_ref() } } // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, by // producing a trait implementations conflict error during compilation, if it does. impl AsRef for FieldTypes { fn as_ref(&self) -> &Helper { &self.0 } } #[test] fn field_types() { let item = FieldTypes(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &f64 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } #[derive(AsRef)] struct FieldTypesWithInner(#[as_ref(i32, Helper)] Helper); // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for FieldTypesWithInner { fn as_ref(&self) -> &bool { self.0.as_ref() } } #[test] fn field_types_with_inner() { let item = FieldTypesWithInner(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &Helper = item.as_ref(); assert!(ptr::eq(rf, &item.0)); } #[derive(AsRef)] struct FieldTypesWithRenamedInner(#[as_ref(i32, RenamedFoo)] Helper); // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for FieldTypesWithRenamedInner { fn as_ref(&self) -> &bool { self.0.as_ref() } } #[test] fn field_types_with_renamed_inner() { let item = FieldTypesWithRenamedInner(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &Helper = item.as_ref(); assert!(ptr::eq(rf, &item.0)); } mod generic { use super::*; #[derive(AsRef)] struct Nothing(T); #[test] fn nothing() { let item = Nothing("test".to_owned()); assert!(ptr::eq(item.as_ref(), &item.0)); } #[derive(AsRef)] #[as_ref(forward)] struct Forward(T); #[test] fn forward() { let item = Forward("test".to_owned()); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } #[derive(AsRef)] struct Field(#[as_ref] T); #[test] fn field() { let item = Field("test".to_owned()); assert!(ptr::eq(item.as_ref(), &item.0)); } #[derive(AsRef)] struct FieldForward(#[as_ref(forward)] T); #[test] fn field_forward() { let item = FieldForward("test".to_owned()); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } #[derive(AsRef)] #[as_ref(i32, f64)] struct Types(T); // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding // to the field type, by producing a trait implementations conflict error during // compilation, if it does. impl> AsRef for Types { fn as_ref(&self) -> &bool { self.0.as_ref() } } #[test] fn types() { let item = Types(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &f64 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } #[derive(AsRef)] #[as_ref(Vec)] struct TypesInner(Vec); #[test] fn types_inner() { let item = TypesInner(vec![1i32]); assert!(ptr::eq(item.as_ref(), &item.0)); } #[derive(AsRef)] struct FieldTypes(#[as_ref(i32, f64)] T); // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding // to the field type, by producing a trait implementations conflict error during // compilation, if it does. impl> AsRef for FieldTypes { fn as_ref(&self) -> &bool { self.0.as_ref() } } #[test] fn field_types() { let item = FieldTypes(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &f64 = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } #[derive(AsRef)] struct FieldTypesInner(#[as_ref(Vec)] Vec); #[test] fn field_types_inner() { let item = FieldTypesInner(vec![1i32]); assert!(ptr::eq(item.as_ref(), &item.0)); } #[derive(AsRef)] #[as_ref(i32)] struct Lifetime<'a>(LifetimeHelper<'a>); #[test] fn lifetime() { let item = Lifetime(LifetimeHelper(&0)); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); } #[derive(AsRef)] struct FieldLifetime<'a>(#[as_ref(i32)] LifetimeHelper<'a>); #[test] fn field_lifetime() { let item = FieldLifetime(LifetimeHelper(&0)); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); } #[derive(AsRef)] #[as_ref([i32])] struct ConstParam(ConstParamHelper); #[test] fn const_param() { let item = ConstParam(ConstParamHelper([])); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); } #[derive(AsRef)] struct FieldConstParam( #[as_ref([i32])] ConstParamHelper, ); #[test] fn field_const_param() { let item = FieldConstParam(ConstParamHelper([])); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); } } } mod named { use super::*; #[derive(AsRef)] struct Nothing { first: String, } #[test] fn nothing() { let item = Nothing { first: "test".to_owned(), }; assert!(ptr::eq(item.as_ref(), &item.first)); } #[derive(AsRef)] #[as_ref(forward)] struct Forward { first: String, } #[test] fn forward() { let item = Forward { first: "test".to_owned(), }; let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } #[derive(AsRef)] struct Field { #[as_ref] first: String, } #[test] fn field() { let item = Field { first: "test".to_owned(), }; assert!(ptr::eq(item.as_ref(), &item.first)); } #[derive(AsRef)] struct FieldForward { #[as_ref(forward)] first: String, } #[test] fn field_forward() { let item = FieldForward { first: "test".to_owned(), }; let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } #[derive(AsRef)] #[as_ref(i32, f64)] struct Types { first: Helper, } // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for Types { fn as_ref(&self) -> &bool { self.first.as_ref() } } // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, by // producing a trait implementations conflict error during compilation, if it does. impl AsRef for Types { fn as_ref(&self) -> &Helper { &self.first } } #[test] fn types() { let item = Types { first: Helper(1, 2.0, false), }; let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &f64 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } #[derive(AsRef)] #[as_ref(i32, Helper)] struct TypesWithInner { first: Helper, } // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for TypesWithInner { fn as_ref(&self) -> &bool { self.first.as_ref() } } #[test] fn types_with_inner() { let item = TypesWithInner { first: Helper(1, 2.0, false), }; let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &Helper = item.as_ref(); assert!(ptr::eq(rf, &item.first)); } type RenamedFoo = Helper; #[derive(AsRef)] #[as_ref(i32, RenamedFoo)] struct TypesWithRenamedInner { first: Helper, } // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for TypesWithRenamedInner { fn as_ref(&self) -> &bool { self.first.as_ref() } } #[test] fn types_with_renamed_inner() { let item = TypesWithRenamedInner { first: Helper(1, 2.0, false), }; let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &Helper = item.as_ref(); assert!(ptr::eq(rf, &item.first)); } #[derive(AsRef)] struct FieldTypes { #[as_ref(i32, f64)] first: Helper, } // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for FieldTypes { fn as_ref(&self) -> &bool { self.first.as_ref() } } // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, by // producing a trait implementations conflict error during compilation, if it does. impl AsRef for FieldTypes { fn as_ref(&self) -> &Helper { &self.first } } #[test] fn field_types() { let item = FieldTypes { first: Helper(1, 2.0, false), }; let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &f64 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } #[derive(AsRef)] struct FieldTypesWithInner { #[as_ref(i32, Helper)] first: Helper, } // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for FieldTypesWithInner { fn as_ref(&self) -> &bool { self.first.as_ref() } } #[test] fn field_types_with_inner() { let item = FieldTypesWithInner { first: Helper(1, 2.0, false), }; let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &Helper = item.as_ref(); assert!(ptr::eq(rf, &item.first)); } #[derive(AsRef)] struct FieldTypesWithRenamedInner { #[as_ref(i32, RenamedFoo)] first: Helper, } // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to // the field type, by producing a trait implementations conflict error during compilation, // if it does. impl AsRef for FieldTypesWithRenamedInner { fn as_ref(&self) -> &bool { self.first.as_ref() } } #[test] fn field_types_with_renamed_inner() { let item = FieldTypesWithRenamedInner { first: Helper(1, 2.0, false), }; let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &Helper = item.as_ref(); assert!(ptr::eq(rf, &item.first)); } mod generic { use super::*; #[derive(AsRef)] struct Nothing { first: T, } #[test] fn nothing() { let item = Nothing { first: "test".to_owned(), }; assert!(ptr::eq(item.as_ref(), &item.first)); } #[derive(AsRef)] #[as_ref(forward)] struct Forward { first: T, } #[test] fn forward() { let item = Forward { first: "test".to_owned(), }; let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } #[derive(AsRef)] struct Field { #[as_ref] first: T, } #[test] fn field() { let item = Field { first: "test".to_owned(), }; assert!(ptr::eq(item.as_ref(), &item.first)); } #[derive(AsRef)] struct FieldForward { #[as_ref(forward)] first: T, } #[test] fn field_forward() { let item = FieldForward { first: "test".to_owned(), }; let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } #[derive(AsRef)] #[as_ref(i32, f64)] struct Types { first: T, } // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding // to the field type, by producing a trait implementations conflict error during // compilation, if it does. impl> AsRef for Types { fn as_ref(&self) -> &bool { self.first.as_ref() } } #[test] fn types() { let item = Types { first: Helper(1, 2.0, false), }; let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &f64 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } #[derive(AsRef)] #[as_ref(Vec)] struct TypesInner { first: Vec, } #[test] fn types_inner() { let item = TypesInner { first: vec![1i32] }; assert!(ptr::eq(item.as_ref(), &item.first)); } #[derive(AsRef)] struct FieldTypes { #[as_ref(i32, f64)] first: T, } // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding // to the field type, by producing a trait implementations conflict error during // compilation, if it does. impl> AsRef for FieldTypes { fn as_ref(&self) -> &bool { self.first.as_ref() } } #[test] fn field_types() { let item = FieldTypes { first: Helper(1, 2.0, false), }; let rf: &i32 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &f64 = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } #[derive(AsRef)] struct FieldTypesInner { #[as_ref(Vec)] first: Vec, } #[test] fn field_types_inner() { let item = FieldTypesInner { first: vec![1i32] }; assert!(ptr::eq(item.as_ref(), &item.first)); } #[derive(AsRef)] #[as_ref(i32)] struct Lifetime<'a> { first: LifetimeHelper<'a>, } #[test] fn lifetime() { let item = Lifetime { first: LifetimeHelper(&0), }; assert!(ptr::eq(item.as_ref(), item.first.as_ref())); } #[derive(AsRef)] struct FieldLifetime<'a> { #[as_ref(i32)] first: LifetimeHelper<'a>, } #[test] fn field_lifetime() { let item = FieldLifetime { first: LifetimeHelper(&0), }; assert!(ptr::eq(item.as_ref(), item.first.as_ref())); } #[derive(AsRef)] #[as_ref([i32])] struct ConstParam { first: ConstParamHelper, } #[test] fn const_param() { let item = ConstParam { first: ConstParamHelper([]), }; assert!(ptr::eq(item.as_ref(), item.first.as_ref())); } #[derive(AsRef)] struct FieldConstParam { #[as_ref([i32])] first: ConstParamHelper, } #[test] fn field_const_param() { let item = FieldConstParam { first: ConstParamHelper([]), }; assert!(ptr::eq(item.as_ref(), item.first.as_ref())); } } } } mod multi_field { use super::*; mod tuple { use super::*; #[derive(AsRef)] struct Nothing(String, i32); #[test] fn nothing() { let item = Nothing("test".to_owned(), 0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } #[derive(AsRef)] struct Skip(String, i32, #[as_ref(skip)] f64); // Asserts that the macro expansion doesn't generate `AsRef` impl for the skipped field, by // producing trait implementations conflict error during compilation, if it does. impl AsRef for Skip { fn as_ref(&self) -> &f64 { &self.2 } } #[test] fn skip() { let item = Skip("test".to_owned(), 0, 0.0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } #[derive(AsRef)] struct Field(#[as_ref] String, #[as_ref] i32, f64); // Asserts that the macro expansion doesn't generate `AsRef` impl for the third field, by // producing trait implementations conflict error during compilation, if it does. impl AsRef for Field { fn as_ref(&self) -> &f64 { &self.2 } } #[test] fn field() { let item = Field("test".to_owned(), 0, 0.0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } #[derive(AsRef)] struct FieldForward(#[as_ref(forward)] String, i32); #[test] fn field_forward() { let item = FieldForward("test".to_owned(), 0); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } type RenamedString = String; #[derive(AsRef)] struct Types( #[as_ref(str, RenamedString)] String, #[as_ref([u8])] Vec, ); // Asserts that the macro expansion doesn't generate `AsRef` impl for the field type, by // producing trait implementations conflict error during compilation, if it does. impl AsRef> for Types { fn as_ref(&self) -> &Vec { &self.1 } } #[test] fn types() { let item = Types("test".to_owned(), vec![0]); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &String = item.as_ref(); assert!(ptr::eq(rf, &item.0)); let rf: &[u8] = item.as_ref(); assert!(ptr::eq(rf, item.1.as_ref())); } mod generic { use super::*; #[derive(AsRef)] struct Nothing(Vec, VecDeque); #[test] fn nothing() { let item = Nothing(vec![1], VecDeque::from([2])); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } #[derive(AsRef)] struct Skip(Vec, VecDeque, #[as_ref(skip)] V); #[test] fn skip() { let item = Skip(vec![1], VecDeque::from([2]), 0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } #[derive(AsRef)] struct Field(#[as_ref] Vec, #[as_ref] VecDeque, V); #[test] fn field() { let item = Field(vec![1], VecDeque::from([2]), 0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } #[derive(AsRef)] struct FieldForward(#[as_ref(forward)] T, U); #[test] fn field_forward() { let item = FieldForward("test".to_owned(), 0); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } #[derive(AsRef)] struct Types(#[as_ref(str)] T, #[as_ref([u8])] U); #[test] fn types() { let item = Types("test".to_owned(), vec![0u8]); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &[u8] = item.as_ref(); assert!(ptr::eq(rf, item.1.as_ref())); } #[derive(AsRef)] struct TypesWithInner( #[as_ref(Vec, [T])] Vec, #[as_ref(str)] U, ); #[test] fn types_with_inner() { let item = TypesWithInner(vec![1i32], "a".to_owned()); let rf: &Vec = item.as_ref(); assert!(ptr::eq(rf, &item.0)); let rf: &[i32] = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.1.as_ref())); } #[derive(AsRef)] struct FieldNonGeneric(#[as_ref([T])] Vec, T); #[test] fn field_non_generic() { let item = FieldNonGeneric(vec![], 2i32); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); } } } mod named { use super::*; #[derive(AsRef)] struct Nothing { first: String, second: i32, } #[test] fn nothing() { let item = Nothing { first: "test".to_owned(), second: 0, }; assert!(ptr::eq(item.as_ref(), &item.first)); assert!(ptr::eq(item.as_ref(), &item.second)); } #[derive(AsRef)] struct Skip { first: String, second: i32, #[as_ref(skip)] third: f64, } // Asserts that the macro expansion doesn't generate `AsRef` impl for the skipped field, by // producing trait implementations conflict error during compilation, if it does. impl AsRef for Skip { fn as_ref(&self) -> &f64 { &self.third } } #[test] fn skip() { let item = Skip { first: "test".to_owned(), second: 0, third: 0.0, }; assert!(ptr::eq(item.as_ref(), &item.first)); assert!(ptr::eq(item.as_ref(), &item.second)); } #[derive(AsRef)] struct Field { #[as_ref] first: String, #[as_ref] second: i32, third: f64, } // Asserts that the macro expansion doesn't generate `AsRef` impl for the `third` field, by // producing trait implementations conflict error during compilation, if it does. impl AsRef for Field { fn as_ref(&self) -> &f64 { &self.third } } #[test] fn field() { let item = Field { first: "test".to_owned(), second: 0, third: 0.0, }; assert!(ptr::eq(item.as_ref(), &item.first)); assert!(ptr::eq(item.as_ref(), &item.second)); } #[derive(AsRef)] struct FieldForward { #[as_ref(forward)] first: String, second: i32, } #[test] fn field_forward() { let item = FieldForward { first: "test".to_owned(), second: 0, }; let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } type RenamedString = String; #[derive(AsRef)] struct Types { #[as_ref(str, RenamedString)] first: String, #[as_ref([u8])] second: Vec, } // Asserts that the macro expansion doesn't generate `AsRef` impl for the field type, by // producing trait implementations conflict error during compilation, if it does. impl AsRef> for Types { fn as_ref(&self) -> &Vec { &self.second } } #[test] fn types() { let item = Types { first: "test".to_owned(), second: vec![0u8], }; let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &String = item.as_ref(); assert!(ptr::eq(rf, &item.first)); let rf: &[u8] = item.as_ref(); assert!(ptr::eq(rf, item.second.as_ref())); } mod generic { use super::*; #[derive(AsRef)] struct Nothing { first: Vec, second: VecDeque, } #[test] fn nothing() { let item = Nothing { first: vec![1], second: VecDeque::from([2]), }; assert!(ptr::eq(item.as_ref(), &item.first)); assert!(ptr::eq(item.as_ref(), &item.second)); } #[derive(AsRef)] struct Skip { first: Vec, second: VecDeque, #[as_ref(skip)] third: V, } #[test] fn skip() { let item = Skip { first: vec![1], second: VecDeque::from([2]), third: 0, }; assert!(ptr::eq(item.as_ref(), &item.first)); assert!(ptr::eq(item.as_ref(), &item.second)); } #[derive(AsRef)] struct Field { #[as_ref] first: Vec, #[as_ref] second: VecDeque, third: V, } #[test] fn field() { let item = Field { first: vec![1], second: VecDeque::from([2]), third: 0, }; assert!(ptr::eq(item.as_ref(), &item.first)); assert!(ptr::eq(item.as_ref(), &item.second)); } #[derive(AsRef)] struct FieldForward { #[as_ref(forward)] first: T, second: U, } #[test] fn field_forward() { let item = FieldForward { first: "test".to_owned(), second: 0, }; let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); } #[derive(AsRef)] struct Types { #[as_ref(str)] first: T, #[as_ref([u8])] second: U, } #[test] fn types() { let item = Types { first: "test".to_owned(), second: vec![0u8], }; let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &[u8] = item.as_ref(); assert!(ptr::eq(rf, item.second.as_ref())); } #[derive(AsRef)] struct TypesWithInner { #[as_ref(Vec, [T])] first: Vec, #[as_ref(str)] second: U, } #[test] fn types_with_inner() { let item = TypesWithInner { first: vec![1i32], second: "a".to_owned(), }; let rf: &Vec = item.as_ref(); assert!(ptr::eq(rf, &item.first)); let rf: &[i32] = item.as_ref(); assert!(ptr::eq(rf, item.first.as_ref())); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.second.as_ref())); } #[derive(AsRef)] struct FieldNonGeneric { #[as_ref([T])] first: Vec, second: T, } #[test] fn field_non_generic() { let item = FieldNonGeneric { first: vec![], second: 2i32, }; assert!(ptr::eq(item.as_ref(), item.first.as_ref())); } } } }