[−][src]Crate structural
This library provides field accessor traits,and emulation of structural types.
Features
These are the features this library provides:
-
Derivation of the 3 accessor traits for every public field (GetField/GetFieldMut/IntoField).
-
Declaration of trait aliases for accessor trait bounds,using field-in-trait syntax. .
Examples
Structural Derive
This demonstrates how you can use any type with a superset of the fields of another one in a function.
For details on the Structural derive macro look here.
use structural::{GetFieldExt,Structural,fp}; fn reads_point4<S>(point:&S) where // The `Structural` derive generated the `Point3D_SI` trait for `Point3D`, // aliasing the accessor traits for it. S:Point3D_SI<u32> { let (a,b,c)=point.fields(fp!( x, y, z )); assert_eq!(a,&0); assert_eq!(b,&11); assert_eq!(c,&33); } fn main(){ reads_point4(&Point3D { x: 0, y: 11, z: 33 }); reads_point4(&Point4D { x: 0, y: 11, z: 33, a: 0xDEAD, }); reads_point4(&Point5D { x: 0, y: 11, z: 33, a: 0xDEAD, b: 0xBEEF, }); } #[derive(Structural)] // Using the `#[struc(public)]` attribute tells the derive macro to // generate the accessor trait impls for non-`pub` fields. #[struc(public)] struct Point3D<T>{ x:T, y:T, z:T, } #[derive(Structural)] // By default only public fields get accessor trait impls, // using `#[struc(public)]` you can have impls to access private fields. #[struc(public)] struct Point4D<T>{ x:T, y:T, z:T, a:T, } #[derive(Structural)] struct Point5D<T>{ pub x:T, pub y:T, pub z:T, pub a:T, pub b:T, }
Structural alias
This demonstrates how you can define a trait aliasing field accessors, using a fields-in-traits syntax.
For more details you can look at the docs for the
structural_alias
macro.
use structural::{GetFieldExt,Structural,structural_alias,fp}; use std::borrow::Borrow; structural_alias!{ trait Person<H:House>{ name:String, house:H, } trait House{ dim:Dimension3D, } } fn print_name<T,H>(this:&T) where T:?Sized+Person<H>, H:House, { let (name,house_dim)=this.fields(fp!( name, house.dim )); println!("Hello, {}!", name); let (w,h,d)=house_dim.fields(fp!( width, height, depth )); if w*h*d >= 1_000_000 { println!("Your house is enormous."); }else{ println!("Your house is normal sized."); } } // most structural aliases are object safe fn print_name_dyn<H>(this:&dyn Person<H>) where H:House, { print_name(this) } #[derive(Structural)] #[struc(public)] struct Dimension3D{ width:u32, height:u32, depth:u32, } ////////////////////////////////////////////////////////////////////////// //// The stuff here could be defined in a separate crate fn main(){ let worker=Worker{ name:"John Doe".into(), salary:Cents(1_000_000_000_000_000), house:Mansion{ dim:Dimension3D{ width:300, height:300, depth:300, }, money_vault_location:"In the basement".into(), } }; let student=Student{ name:"Jake English".into(), birth_year:1995, house:SmallHouse{ dim:Dimension3D{ width:30, height:30, depth:30, }, residents:10, } }; print_name(&worker); print_name(&student); print_name_dyn(&worker); print_name_dyn(&student); } #[derive(Structural)] // Using the `#[struc(public)]` attribute tells the derive macro to // generate the accessor trait impls for non-`pub` fields. #[struc(public)] struct Worker{ name:String, salary:Cents, house:Mansion, } #[derive(Structural)] #[struc(public)] struct Student{ name:String, birth_year:u32, house:SmallHouse, } #[derive(Structural)] #[struc(public)] struct Mansion{ dim:Dimension3D, money_vault_location:String, } #[derive(Structural)] #[struc(public)] struct SmallHouse{ dim:Dimension3D, residents:u32, }
Anonymous structs (make_struct
macro)
This demonstrates how you can construct an anonymous struct.
For more details you can look at the docs for the
make_struct
macro.
use structural::{GetFieldExt,make_struct,structural_alias,fp}; structural_alias!{ trait Person<T>{ // We only have shared access (`&String`) to the field. ref name:String, // We have shared,mutable,and by value access to the field. // Not specifying any of `mut`/`ref`/`move` is equivalent to `mut move value:T,` value:T, } } fn make_person(name:String)->impl Person<()> { make_struct!{ name, value: (), } } fn print_name<T>(mut this:T) where T:Person<Vec<String>>, { println!("Hello, {}!",this.field_(fp!(name)) ); let list=vec!["what".into()]; *this.field_mut(fp!(value))=list.clone(); assert_eq!( this.field_(fp!(value)), &list ); assert_eq!( this.into_field(fp!(value)), list ); } // most structural aliases are object safe fn print_name_dyn(this:&mut dyn Person<Vec<String>>){ println!("Hello, {}!",this.field_(fp!(name)) ); let list=vec!["what".into()]; *this.field_mut(fp!(value))=list.clone(); assert_eq!( this.field_(fp!(value)), &list ); } ////////////////////////////////////////////////////////////////////////// //// The stuff here could be defined in a separate crate fn main(){ let worker=make_struct!{ // This derives clone for the anonymous struct #![derive(Clone)] name:"John Doe".into(), salary:Cents(1_000_000_000_000_000), value:vec![], }; let student=make_struct!{ // This derives clone for the anonymous struct #![derive(Clone)] name:"Jake English".into(), birth_year:1995, value:vec![], }; print_name(worker.clone()); print_name(student.clone()); print_name_dyn(&mut worker.clone()); print_name_dyn(&mut student.clone()); let person=make_person("Louis".into()); assert_eq!( person.field_(fp!(name)), "Louis" ); assert_eq!( person.field_(fp!(value)), &() ); } #[derive(Debug,Copy,Clone,PartialEq,Eq)] struct Cents(u64);
Re-exports
pub extern crate std; |
pub use crate::field_traits::GetField; |
pub use crate::field_traits::GetFieldMut; |
pub use crate::field_traits::IntoField; |
pub use crate::field_traits::IntoFieldMut; |
pub use crate::field_traits::GetFieldType; |
pub use crate::field_traits::GetFieldType2; |
pub use crate::field_traits::GetFieldType3; |
pub use crate::field_traits::GetFieldType4; |
pub use crate::field_traits::RevGetFieldType; |
pub use crate::field_traits::RevGetFieldType_; |
pub use crate::structural_trait::Structural; |
pub use crate::structural_trait::StructuralDyn; |
Modules
docs | Documentation for proc-macros and guides. |
field_traits | Accessor and extension traits for fields. |
mut_ref | A wrapper type for a mutable pointer with a lifetime. |
reexports | Reexports from the |
structural_trait | Contains the Structural trait with info about the fields that have accessor trait impls. |
type_level | Contains types representing values. |
utils | Some helper functions. |
Macros
FP | Constructs a FieldPath(Set) for use as a generic parameter. |
field_path_aliases | Declares aliases for field paths,used to access fields. |
field_path_aliases_module | Declares a module with aliases for field paths,used to access fields. |
fp | Constructs a FieldPath(Set) value, which determines the fields accessed in GetFieldExt methods. |
make_struct | Constructs an anonymous struct, which implements all the accessor traits for its field. |
structural_alias | The |
z_delegate_structural_with | This macro allows delegating the implementation of the Structural and field accessor traits. |
z_impl_box_into_field_method | For use in manual implementations of the IntoField trait. |
z_unsafe_impl_get_field_raw_mut_method | For manual implementors of the GetFieldMut trait, implementing the methods used for accession multiple mutable fields. |
Traits
GetFieldExt | A trait defining the primary way to call methods from structural traits. |
Derive Macros
Structural | This macro is documented in structural::docs::structural_macro |