[][src]Crate structural

This library provides abstractions over fields,emulating 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,ti};

#[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,
}


fn reads_point4<S>(point:&S)
where
    // The `Structural` derive macro generated the `Point3D_SI` trait,
    // aliasing the accessor traits for Point3D.
    S:Point3D_SI<u32>
{
    let (a,b,c)=point.fields(ti!(x,y,z));
    
    assert_eq!(a,&0);
    assert_eq!(b,&11);
    assert_eq!(c,&33);
}

//////////////////////////////////////////////////////////////////////////
////        In another crate

#[derive(Structural)]
#[struc(public)]
// Using the `#[struc(access="mut move")]` attribute tells the derive macro to 
// generate the accessor trait for accessing the 
// fields by reference/mutable-reference/by value,
// when by default it only impls the by-reference one.
#[struc(access="mut move")]
struct Point4D<T>{
    x:T,
    y:T,
    z:T,
    a:T,
}

#[derive(Structural)]
#[struc(public)]
// Using the `#[struc(access="move")]` attribute tells the derive macro to 
// generate the accessor trait for accessing the 
// fields by reference/by value,when by default it only impls the by-reference one.
#[struc(access="move")]
struct Point5D<T>{
    x:T,
    y:T,
    z:T,
    a:T,
    b:T,
}


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,
});

Structural alias

This demonstrates how you can define a trait alias for a single read-only field accessor.

For more details you can look at the docs for the structural_alias macro.

use structural::{GetFieldExt,Structural,structural_alias,ti};

use std::borrow::Borrow;

structural_alias!{
    trait Person<S>{
        name:S,
    }
}

fn print_name<T,S>(this:&T)
where
    T:Person<S>,
    S:Borrow<str>,
{
    println!("Hello, {}!",this.field_(ti!(name)).borrow() )
}

// most structural aliases are object safe
fn print_name_dyn<  S>(this:&dyn Person<S>)
where
    S:Borrow<str>,
{
    println!("Hello, {}!",this.field_(ti!(name)).borrow() )
}


//////////////////////////////////////////////////////////////////////////
////          The stuff here could be defined in a separate crate

#[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,
}

#[derive(Structural)]
#[struc(public)]
struct Student{
    name:String,
    birth_year:u32,
}


fn main(){
    let worker=Worker{
        name:"John Doe".into(),
        salary:Cents(1_000_000_000_000_000),
    };

    let student=Student{
        name:"Jake English".into(),
        birth_year:1995,
    };

    print_name(&worker);
    print_name(&student);

    print_name_dyn(&worker);
    print_name_dyn(&student);
}

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,ti};

structural_alias!{
    trait Person<T>{
        // We only have shared access (`&String`) to the field.
        name:String,
        // We have shared,mutable,and by value access to the field.
        mut move value:T,
    }
}

fn print_name<T>(mut this:T)
where
    T:Person<Vec<String>>,
{
    println!("Hello, {}!",this.field_(ti!(name)) );

    let list=vec!["what".into()];
    *this.field_mut(ti!(value))=list.clone();
    assert_eq!( this.field_(ti!(value)), &list );
    assert_eq!( this.into_field(ti!(value)), list );
}

// most structural aliases are object safe
fn print_name_dyn(mut this:Box<dyn Person<Vec<String>>>){
    println!("Hello, {}!",this.field_(ti!(name)) );

    let list=vec!["what".into()];
    *this.field_mut(ti!(value))=list.clone();
    assert_eq!( this.field_(ti!(value)), &list );
    assert_eq!( this.box_into_field(ti!(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(Box::new(worker));
print_name_dyn(Box::new(student));

}

#[derive(Debug,Copy,Clone,PartialEq,Eq)]
struct Cents(u64);

Re-exports

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::GetFieldExt;
pub use crate::field_traits::GetFieldType;
pub use crate::structural_trait::Structural;
pub use crate::structural_trait::StructuralDyn;

Modules

chars

Type-level ascii characters and bytes.

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

TI

Constructs a type-level identifier for use as a generic parameter.

TList

Type macro for a type-list.

declare_names_module

Declares a module with aliases for type-level idents,used to access fields.

delegate_structural_with

This macro allows delegating the implementation of the Structural and field accessor traits.

impl_box_into_field_method

For use in manual implementations of the IntoField trait.

impl_structural_dyn

Implements StructuralDyn for some type,by delegating to Structural.

make_struct

Constructs an anonymous struct, which implements the IntoFieldMut accessor trait for all its field.

structural_alias

The structural_alias defines a trait alias for multiple field accessors.

ti

Constructs field identifier(s) (TString/TStringSet).

tlist

Instantiates a type-list, which is a zero-sized-type which does not contain instances of the types it lists.

unsafe_impl_get_field_raw_mut_method

For manual implementors of the GetFieldMut trait, implementing the methods used for accession multiple mutable fields.

Derive Macros

Structural

This macro is documented in structural::docs::structural_macro