[][src]Crate structural

This library provides field accessor traits,and emulation of structural types.

Features

These are the features this library provides:

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 core_extensions crate.

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 structural_alias macro defines a trait alias for multiple field accessors.

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