Quack - Duck typing traits

Duck typing is a method where code works when certain methods and properties are present, instead of requiring a certain type.

Design

An duck typing abstraction is composed from the following building blocks:

Is is common to declare a newtype for each property and action.

For example, declare pub struct X(pub f64); for Get<X> and Set<X>.

The quack! macro can be used to implement simple get/set properties.

Get, Set and Action traits are auto implemented for &RefCell<T> and Rc<RefCell<T>>. This simplifies working with dynamic borrowing in a single thread.

Example

```rust extern crate quack;

use quack::*;

[derive(Copy, Clone, Debug)]

pub struct Tire {pub winter: bool}

[derive(Debug, Clone)]

pub struct Car {pub tires: [Tire; 4]}

pub struct LeftFrontTire(pub Tire); pub struct RightFrontTire(pub Tire); pub struct LeftBackTire(pub Tire); pub struct RightBackTire(pub Tire);

quack!{ for Car { getset LeftFrontTire(self.tires[0]), getset RightFrontTire(self.tires[1]), getset LeftBackTire(self.tires[2]), getset RightBackTire(self.tires[3]), } }

pub struct ShiftToWinterTires; impl Action for Car { type Result = (); fn action(&mut self, _: ShiftToWinterTires) -> () { for i in 0..4 {self.tires[i].winter = true} } }

pub struct ShiftToSummerTires; impl Action for Car { type Result = (); fn action(&mut self, _: ShiftToSummerTires) -> () { for i in 0..4 {self.tires[i].winter = false} } }

// Implement trait on top of duck type object. pub trait GenericCar: GetSet + GetSet + GetSet + GetSet + Action + Action { fn leftfronttire(&self) -> Tire {Get::::get(self).0} fn rightfronttire(&self) -> Tire {Get::::get(self).0} fn leftbacktire(&self) -> Tire {Get::::get(self).0} fn rightbacktire(&self) -> Tire {Get::::get(self).0}

fn set_left_front_tire(&mut self, val: Tire) {self.set(LeftFrontTire(val))}
fn set_right_front_tire(&mut self, val: Tire) {self.set(RightFrontTire(val))}
fn set_left_back_tire(&mut self, val: Tire) {self.set(LeftBackTire(val))}
fn set_right_back_tire(&mut self, val: Tire) {self.set(RightBackTire(val))}

fn shift_to_winter_tires(&mut self) {self.action(ShiftToWinterTires);}
fn shift_to_summer_tires(&mut self) {self.action(ShiftToSummerTires);}

}

// Auto implement GenericCar. impl GenericCar for T where T: GetSet + GetSet + GetSet + GetSet + Action + Action {}

fn main() { let mut car = Car {tires: [Tire {winter: false}; 4]};

car.shift_to_winter_tires();
println!("{:?}", car);

car.set_left_front_tire(Tire {winter: false});
println!("Left front tire: {:?}", car.left_front_tire());

} ```