[][src]Trait structural::GetFieldExt

pub trait GetFieldExt {
    fn field_<'a, P>(&'a self, path: P) -> RevFieldRefType<'a, P, Self>
    where
        P: IsFieldPath,
        P: RevGetField<'a, Self>
, { ... }
fn fields<'a, P>(&'a self, path: P) -> RevFieldRefType<'a, P, Self>
    where
        P: RevGetField<'a, Self>
, { ... }
fn cloned_fields<'a, P>(
        &'a self,
        path: P
    ) -> <RevFieldRefType<'a, P, Self> as Cloned>::Cloned
    where
        P: RevGetField<'a, Self>,
        RevFieldRefType<'a, P, Self>: Cloned
, { ... }
fn field_mut<'a, P>(&'a mut self, path: P) -> RevFieldMutType<'a, P, Self>
    where
        P: IsFieldPath,
        P: RevGetFieldMut<'a, Self>
, { ... }
fn fields_mut<'a, P>(&'a mut self, path: P) -> RevFieldMutType<'a, P, Self>
    where
        P: IsFieldPathSet<PathUniqueness = UniquePaths>,
        P: RevGetFieldMut<'a, Self>
, { ... }
fn into_field<'a, P>(self, path: P) -> RevIntoFieldType<'a, P, Self>
    where
        P: IsFieldPath,
        P: RevIntoField<'a, Self>,
        Self: Sized
, { ... }
fn box_into_field<'a, P>(
        self: Box<Self>,
        path: P
    ) -> RevIntoFieldType<'a, P, Self>
    where
        P: RevIntoField<'a, Self>
, { ... } }

A trait defining the primary way to call methods from structural traits.

Provided methods

fn field_<'a, P>(&'a self, path: P) -> RevFieldRefType<'a, P, Self> where
    P: IsFieldPath,
    P: RevGetField<'a, Self>, 

Gets a reference to a field,determined by path.

This is named field_ instead of field because field collides with the DebugTuple/DebugStruct method

Example

use structural::{GetFieldExt,fp,structural_alias};

structural_alias!{
    trait EvenFields<A,B,C>{
        0:A,
        2:B,
        4:C,
    }
}

fn with_even<T>(this:&T)
where
    T:EvenFields<u32,u32,u32>
{
    assert_eq!( this.field_(fp!(0)), &1 );
    assert_eq!( this.field_(fp!(2)), &2 );
    assert_eq!( this.field_(fp!(4)), &5 );
}

fn main(){
    with_even( &(1,0,2,0,5) );
    with_even( &(1,0,2,0,5,0) );
    with_even( &(1,0,2,0,5,0,0) );
    with_even( &(1,0,2,0,5,0,0,0) );
}

fn fields<'a, P>(&'a self, path: P) -> RevFieldRefType<'a, P, Self> where
    P: RevGetField<'a, Self>, 

Gets references to multiple fields,determined by path.

Example

use structural::{GetFieldExt,fp,structural_alias};

structural_alias!{
    trait OddFields<A,B,C>{
        1:A,
        3:B,
        5:C,
    }
}

fn with_even(this:&impl OddFields<u32,u32,u32>){
    assert_eq!( this.fields(fp!(1,3,5)), (&22,&44,&77) );
}

fn main(){
    with_even( &(0,22,0,44,0,77) );
    with_even( &(0,22,0,44,0,77,0) );
    with_even( &(0,22,0,44,0,77,0,0) );
    with_even( &(0,22,0,44,0,77,0,0,0) );
}

fn cloned_fields<'a, P>(
    &'a self,
    path: P
) -> <RevFieldRefType<'a, P, Self> as Cloned>::Cloned where
    P: RevGetField<'a, Self>,
    RevFieldRefType<'a, P, Self>: Cloned

Gets clones of multiple fields,determined by path.

Example

This example also uses the reexported IntoArray trait, which allows converting homogeneous tuples to arrays, in this case it's used to iterate over the fields.

use structural::{GetFieldExt,Structural,fp,make_struct};
use structural::reexports::IntoArray;
 
// The `Fruits_SI` trait was declared by the `Structural` derive on `Fruits`.
fn total_fruit_count(fruits:&dyn Fruits_SI)->u32{
    fruits
        .cloned_fields(fp!( apples, oranges, tangerines, tomatoes ))
        .into_array()
        .iter()
        .sum()
}
 
{
    let fruits=Fruits{
        apples:1,
        oranges:2,
        tangerines:3,
        tomatoes:5,
    };
     
    assert_eq!( total_fruit_count(&fruits), 11 );
}
 
{
    let fruits=make_struct!{
        apples:8,
        oranges:13,
        tangerines:21,
        tomatoes:34,
    };
     
    assert_eq!( total_fruit_count(&fruits), 76 );
}
 
#[derive(Structural)]
// We only get read access to the fields.
#[struc(public,access="ref")]
struct Fruits{
    apples:u32,
    oranges:u32,
    tangerines:u32,
    tomatoes:u32,
}
 

fn field_mut<'a, P>(&'a mut self, path: P) -> RevFieldMutType<'a, P, Self> where
    P: IsFieldPath,
    P: RevGetFieldMut<'a, Self>, 

Gets a mutable reference to a field,determined by path.

Example

use structural::{GetFieldExt,fp,make_struct,Structural};

#[derive(Structural)]
struct Human{
    pub x:i32,
    pub y:i32,
    pub health:u32,
    flags:u32,
}

// The `Human_SI` trait was declared by the `Structural` derive on `Human`.
fn move_human( this:&mut dyn Human_SI, dx:i32, dy:i32 ){
    *this.field_mut(fp!(x))+=dx;
    *this.field_mut(fp!(y))+=dy;
}

{
    let mut entity=make_struct!{
        x: 0, 
        y: 0, 
        health: 100,
    };
    move_human(&mut entity,-100,300);
    assert_eq!( entity.fields(fp!(x,y,health)), (&-100,&300,&100) )
}
{
    let mut entity=Human{
        x: -1000,
        y: 1000,
        health: 1,
        flags: 0b11111,
    };
     
    move_human(&mut entity,500,-200);

    assert_eq!( entity.x, -500 );
    assert_eq!( entity.y, 800 );
    assert_eq!( entity.health, 1 );
    assert_eq!( entity.flags, 0b11111 );
}

fn fields_mut<'a, P>(&'a mut self, path: P) -> RevFieldMutType<'a, P, Self> where
    P: IsFieldPathSet<PathUniqueness = UniquePaths>,
    P: RevGetFieldMut<'a, Self>, 

Gets mutable references to multiple fields,determined by path.

Example

use structural::{
    GetFieldExt,GetFieldMut,GetFieldType,Structural,
    fp,field_path_aliases_module,
};

field_path_aliases_module!{ 
    mod names{x,y}
}

fn swap_coordinates<T,U>(this:&mut T)
where
    T:GetFieldMut<names::x,Ty=U>,
    T:GetFieldMut<names::y,Ty=U>,
{
    let (x,y)=this.fields_mut(fp!(x,y));
    std::mem::swap(x,y);
}
 
{
    let mut this=Point2D{ x:100, y:300 };
    swap_coordinates(&mut this);
    assert_eq!( this.x, 300 );
    assert_eq!( this.y, 100 );
}
 
{
    let mut this=Point3D{ x:30, y:0, z:500 };
    swap_coordinates(&mut this);
    assert_eq!( this.x, 0 );
    assert_eq!( this.y, 30 );
    assert_eq!( this.z, 500 );
}

#[derive(Structural)]
struct Point2D<T>{
    pub x:T,
    pub y:T,
}

#[derive(Structural)]
struct Point3D<T>{
    pub x:T,
    pub y:T,
    pub z:T,
}

Example

An example of how this method does not allow multiple mutable borrows of the same field.

This example deliberately fails to compile
use structural::{GetFieldExt,fp};

let mut tup=(1,1,2,3,5,8);

let _=tup.fields_mut(fp!(4,4));

fn into_field<'a, P>(self, path: P) -> RevIntoFieldType<'a, P, Self> where
    P: IsFieldPath,
    P: RevIntoField<'a, Self>,
    Self: Sized

Converts ´self´ into a field,determined by path.

Example

use structural::{GetFieldExt,Structural,fp};
 
 
#[derive(Structural,Clone)]
#[struc(public,access="move")]
struct Tupled<T>(T,T,T,T);
 
// The `Tupled_SI` trait was declared by the `Structural` derive on `Tupled`.
fn pick_index<T>(this:impl Tupled_SI<T>,which_one:u32)->T{
    match which_one % 4 {
        0=>this.into_field(fp!(0)),
        1=>this.into_field(fp!(1)),
        2=>this.into_field(fp!(2)),
        _=>this.into_field(fp!(3)),
    }
}
 
{
    let tup=Tupled(13,21,34,55);
     
    assert_eq!( pick_index(tup.clone(),0), 13 );
    assert_eq!( pick_index(tup.clone(),1), 21 );
    assert_eq!( pick_index(tup.clone(),2), 34 );
    assert_eq!( pick_index(tup        ,3), 55 );
}
 
{
    let array=[13,21,34,55];
     
    assert_eq!( pick_index(array.clone(),0), 13 );
    assert_eq!( pick_index(array.clone(),1), 21 );
    assert_eq!( pick_index(array.clone(),2), 34 );
    assert_eq!( pick_index(array        ,3), 55 );
}
 

fn box_into_field<'a, P>(
    self: Box<Self>,
    path: P
) -> RevIntoFieldType<'a, P, Self> where
    P: RevIntoField<'a, Self>, 

Converts a boxed ´self´ into a field,determined by path.

Example

use structural::{GetFieldExt,Structural,fp,make_struct,structural_alias};
 
structural_alias!{
    trait Pair<T>{
        left :T,
        right:T,
    }
}
 
fn pick_from_pair<T>(this:Box<dyn Pair<T>>,which_one:u32)->T{
    match which_one%2 {
        0=>this.box_into_field(fp!(left )),
        _=>this.box_into_field(fp!(right)),
    }
}
 
fn main(){
    let this=Box::new(make_struct!{
        #![derive(Clone)]
        left: "foo".to_string(),
        right: "bar".to_string(),
    });
 
    assert_eq!( pick_from_pair(this.clone(),0), "foo" );
    assert_eq!( pick_from_pair(this        ,1), "bar" );
}
 
Loading content...

Implementors

impl<T: ?Sized> GetFieldExt for T[src]

Loading content...