Derive Macro former::ComponentsAssign

source ·
#[derive(ComponentsAssign)]
{
    // Attributes available to this derive:
    #[debug]
}
Expand description

Derives the ComponentsAssign trait for a struct, enabling components_assign which set all fields at once.

This will work only if every field can be acquired from the passed value. In other words, the type passed as an argument to components_assign must implement Into for each field type.

§Attributes

  • debug : An optional attribute to enable debugging of the trait derivation process.

§Conditions

  • This macro is only enabled when the derive_components_assign feature is active in your Cargo.toml.
  • The type must implement ComponentAssign (derive( ComponentAssign ))

§Limitations

This trait cannot be derived, if the struct has fields with identical types

§Input Code Example

An example when we encapsulate parameters passed to a function in a struct.

use former::{ ComponentAssign, ComponentsAssign };

#[ derive( Default, ComponentAssign, ComponentsAssign ) ]
struct BigOpts
{
  cond : bool,
  int : i32,
  str : String,
}

#[ derive( Default, ComponentAssign, ComponentsAssign ) ]
struct SmallerOpts
{
  cond: bool,
  int: i32,
}

impl From< &BigOpts > for bool
{
  fn from( value : &BigOpts ) -> Self
  {
    value.cond
  }
}

impl From< &BigOpts > for i32
{
  fn from( value: &BigOpts ) -> Self
  {
    value.int
  }
}

fn take_big_opts( options : &BigOpts ) -> &String
{
  &options.str
}

fn take_smaller_opts( options : &SmallerOpts ) -> bool
{
  !options.cond
}

let options1 = BigOpts
{
  cond : true,
  int : -14,
  ..Default::default()
};
take_big_opts( &options1 );

let mut options2 = SmallerOpts::default();
options2.smaller_opts_assign( &options1 );
take_smaller_opts( &options2 );

Which expands approximately into :

use former::{ ComponentAssign, ComponentsAssign };

#[derive(Default)]
struct BigOpts
{
  cond : bool,
  int : i32,
  str : String,
}

impl< IntoT > ComponentAssign< bool, IntoT > for BigOpts
where
  IntoT : Into< bool >,
{
  fn assign( &mut self, component : IntoT )
  {
    self.cond = component.into();
  }
}

impl< IntoT > ComponentAssign< i32, IntoT > for BigOpts
where
  IntoT : Into< i32 >,
{
  fn assign( &mut self, component : IntoT )
  {
    self.int = component.into();
  }
}

impl< IntoT > ComponentAssign< String, IntoT > for BigOpts
where
  IntoT : Into< String >,
{
  fn assign( &mut self, component : IntoT )
  {
    self.str = component.into();
  }
}

pub trait BigOptsComponentsAssign< IntoT >
where
  IntoT : Into< bool >,
  IntoT : Into< i32 >,
  IntoT : Into< String >,
  IntoT : Clone,
{
  fn components_assign( &mut self, component : IntoT );
}

impl< T, IntoT > BigOptsComponentsAssign< IntoT > for T
where
  T : former::ComponentAssign< bool, IntoT >,
  T : former::ComponentAssign< i32, IntoT >,
  T : former::ComponentAssign< String, IntoT >,
  IntoT : Into< bool >,
  IntoT : Into< i32 >,
  IntoT : Into< String >,
  IntoT : Clone,
{
  fn components_assign( &mut self, component : IntoT )
  {
    former::ComponentAssign::< bool, _ >::assign( self, component.clone() );
    former::ComponentAssign::< i32, _ >::assign( self, component.clone() );
    former::ComponentAssign::< String, _ >::assign( self, component.clone() );
  }
}

#[derive(Default)]
struct SmallerOpts
{
  cond : bool,
  int : i32,
}

impl< IntoT > ComponentAssign< bool, IntoT > for SmallerOpts
where
  IntoT : Into< bool >,
{
  fn assign( &mut self, component : IntoT )
  {
    self.cond = component.into();
  }
}

impl< IntoT > ComponentAssign< i32, IntoT > for SmallerOpts
where
    IntoT : Into< i32 >,
{
  fn assign( &mut self, component : IntoT )
  {
    self.int = component.into();
  }
}

pub trait SmallerOptsComponentsAssign< IntoT >
where
  IntoT : Into< bool >,
  IntoT : Into< i32 >,
  IntoT : Clone,
{
  fn smaller_opts_assign( &mut self, component : IntoT );
}

impl< T, IntoT > SmallerOptsComponentsAssign< IntoT > for T
where
  T : former::ComponentAssign< bool, IntoT >,
  T : former::ComponentAssign< i32, IntoT >,
  IntoT : Into< bool >,
  IntoT : Into< i32 >,
  IntoT : Clone,
{
  fn smaller_opts_assign( &mut self, component : IntoT )
  {
    former::ComponentAssign::< bool, _ >::assign( self, component.clone() );
    former::ComponentAssign::< i32, _ >::assign( self, component.clone() );
  }
}

impl From< &BigOpts > for bool
{
  fn from( value : &BigOpts ) -> Self
  {
    value.cond
  }
}

impl From< &BigOpts > for i32
{
  fn from( value : &BigOpts ) -> Self
  {
    value.int
  }
}

fn take_big_opts( options : &BigOpts ) -> &String
{
  &options.str
}

fn take_smaller_opts( options : &SmallerOpts ) -> bool
{
  !options.cond
}

let options1 = BigOpts
{
  cond : true,
  int : -14,
  ..Default::default()
};
take_big_opts( &options1 );
let mut options2 = SmallerOpts::default();
options2.smaller_opts_assign( &options1 );
take_smaller_opts( &options2 );