[−][src]Macro structural::z_delegate_structural_with
This macro allows delegating the implementation of the Structural and field accessor traits.
This macro delegates the implementation of those traits for all fields, it doesn't provide a way to do so for only a list of fields.
Safety
The unsafety of implementing GetFieldMut with this macro comes from the methods used to do multiple mutable borrows.
You must ensure that the variable that you delegate GetField to is the same as the one you delegate GetFieldMut to, as well as ensuring that there are no other impls of the GetFieldMut trait borrowing from the same variable mutably.
Example with all syntax
use structural::z_delegate_structural_with; use structural::mut_ref::MutRef; struct Foo<T>{ value:T } z_delegate_structural_with!{ impl[T,] Foo<T> // This where clause is required syntax where[ T:Trait, ] // This is the identifier used for `self` in the blocks bellow. self_ident=this; // This is the type of the variable we delegate to, // this is required because Rust doesn't have a `typeof`/`decltype` construct. delegating_to_type=T; // `field_name` is the name for a `PhantomData` parameter in // `GetFieldMut::get_field_raw_mut` // (usable from `as_delegating_raw{}` in this macro), // with the name of the field being accessed // // `FieldName` is the name of the type parameter that represents the // name of the field being accessed. field_name_param=( field_name : FieldName ); // This block of code is used to get the reference to the delegating variable // in GetField. GetField { &this.value } // This block of code is used to get a mutable reference to the delegating variable // in GetFieldMut // // This is `unsafe` because this block must always evaluate to a mutable reference // for the same variable, // and it must not be the same variable as other implementations of the GetFieldMut trait unsafe GetFieldMut where [ // This is an optional where clause // The last where predicate must have a trailing comma. T:Trait, ]{ &mut this.value } // This gets a raw mutable pointer to the variable this delegates to. as_delegating_raw{ &mut (*this).value as *mut T } // This block of code is used to get the delegating variable by value in IntoField. IntoField where [ // This is an optional where clause // The last where predicate must have a trailing comma. T:Trait, ]{ this.value } }
Example
This example is of a type wrapping a ManuallyDrop<T>,delegating to the T inside it.
use std::{ fmt::Debug, mem::ManuallyDrop, }; use structural::{GetFieldExt,GetFieldMut,z_delegate_structural_with,make_struct,fp}; use structural::mut_ref::MutRef; struct Bar<T>{ value:ManuallyDrop<T> } impl<T> Bar<T>{ pub fn new(value:T)->Self{ Self{ value:ManuallyDrop::new(value) } } } z_delegate_structural_with!{ // You must write a trailing comma. impl[T,] Bar<T> where[ // This requires T to implement Clone // for `Bar<T>` to implement the accessor traits T:Clone ] self_ident=this; delegating_to_type=T; field_name_param=( field_name : FieldName ); GetField { &*this.value } unsafe GetFieldMut where [T:Debug,] { &mut *this.value } as_delegating_raw{ &mut (*this).value as *mut ManuallyDrop<T> as *mut T } IntoField where [T:Debug,] { ManuallyDrop::into_inner(this.value) } } { let mut bar=Bar::new((2,3,5,8,13)); assert_eq!( bar.fields(fp!(4,3,2,1,0)), ( &13, &8, &5, &3, &2 ) ); assert_eq!( bar.fields_mut(fp!(1,2,3,4)), ( &mut 3, &mut 5, &mut 8, &mut 13 ) ); assert_eq!(bar.into_field(fp!(1)),3); } { let mut bar=Bar::new(make_struct!{ #![derive(Clone,Debug)] //This derives Clone and Debug for the anonymous struct a:"hello", b:"world", c:"tour", }); assert_eq!( bar.fields(fp!(a,b,c)), ( &"hello", &"world", &"tour" ) ); assert_eq!( bar.fields_mut(fp!(c,b,a)), ( &mut"tour", &mut"world", &mut"hello" ) ); assert_eq!( bar.into_field(fp!(c)), "tour" ); }