constduck 0.1.0

Compile-time ducktyping and reflection using const generics
constduck-0.1.0 doesn't have any documentation.

constduck implements compile-time duck typing via const generics. It only works on structs.

Note: if you can, use a custom trait instead of constduck. Only use constduck in cases where you can't implement a custom trait.

You must #[derive(ConstDuck)] on all traits that you want to duck-type. For example:

# #![feature(adt_const_params)]
# use constduck::*;
#[derive(ConstDuck)]
struct Donald {
money: i64,
}

This implements Field<"money"> and ConstructFrom<T: WithField<"money">> for Donald.

You can use constduck to derive implementations for traits, like #[derive(..)]. See [constduck/examples/debug-print.rs] for an example. The example implements a trait (MyPrint) for all types that derive ConstDuck.

You can use [Field::get], [Field::get_consume] and [Field::set] to access the fields of the struct. For example:

# #![feature(adt_const_params)]
# use constduck::*;
use std::ops::Sub;

#[derive(ConstDuck)]
struct Donald {
money: i8,
}

#[derive(ConstDuck)]
struct Scrooge {
money: i64,
}

let mut donald = Donald { money: 5 };
let mut scrooge = Scrooge { money: 1_000_000_000 };

fn deduct_money<N, T: Field<"money", Ty = N>>(t: &mut T)
where N: Clone,
N: Sub<N, Output = N>,
N: From<i8> {
t.set(t.get().clone() - N::from(5i8));
}

assert_eq!(donald.money, 5);
deduct_money(&mut donald);
assert_eq!(donald.money, 0);

assert_eq!(scrooge.money, 1_000_000_000);
deduct_money(&mut scrooge);
assert_eq!(scrooge.money, 0_999_999_995);

The main use case for constduck is in macros. You sometimes need to specify a type in a macro. If you only know the type of the struct, it is normally impossible to obtain the type of a field. With constduck, you can write this type using generics. For example:

# #![feature(adt_const_params)]
# use constduck::*;
macro_rules! make_getter {
($struct:ident.$field:ident) => {
impl<T> $struct
where Self: Field<{ stringify!($field) }, Ty = T> {
pub fn $field(&self) -> &T {
<Self as Field<{ stringify!($field) }>>::get(self)
}
}
}
}

#[derive(ConstDuck)]
struct Foo {
bar: String,
baz: u32,
}

make_getter!(Foo.bar);