Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Syntactic sugar for getters + setters
trait GetSet<G,S> {
fn get(&self) -> G;
fn set(&self) -> S;
}
macro_rules! field {
($s:ident . $f:ident) => ($s.get().$f(&$s));
($s:ident . $f:ident = $v:expr) => ($s.set().$f(&mut $s, $v));
(
struct $s:ident: $m:ident {
$(
$n:ident: $t:ty =>
|$getprev:ident| $getbody:expr,
|$setprev:ident, $setnew:ident| $setbody:expr
)*
}
) => {
#[allow(non_snake_case)] // concat_idents! can't come soon enough
mod $m {
struct Get;
impl Get {
$(
pub fn $n(self, s: &$s) -> $t {
let $getprev = s.$n;
$getbody
}
),*
}
struct Set;
impl Set {
$(
pub fn $n(self, s: &mut $s, $setnew: $t) {
let $setprev = s.$n;
s.$n = $setbody;
}
),*
}
pub struct $s {
$(
pub $n: $t
),*
}
impl super::GetSet<Get, Set> for $s {
fn get(&self) -> Get { Get }
fn set(&self) -> Set { Set }
}
}
use $m::$s;
}
}
field! {
struct A: MA {
i: i32 =>
|prev| { // just print the value as it is read
println!("get i which is {}", prev);
prev
},
|prev, new| { // clamp the value to a maximum of 42
println!("set i which was {} to {}", prev, new);
if new <= 42 { new } else { 42 }
}
}
}
impl A {
fn new(i: i32) -> A {
A { i: i }
}
}
fn main() {
let mut a = A::new(42);
println!("{:?}", field!(a.i));
field!(a.i = 43);
println!("{:?}", field!(a.i));
field!(a.i = 41);
println!("{:?}", field!(a.i));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment