Skip to content

Instantly share code, notes, and snippets.

@SpaceManiac
Created April 29, 2017 04:16
Show Gist options
  • Save SpaceManiac/22c8505d92ef3b228fb41ec9694836ab to your computer and use it in GitHub Desktop.
Save SpaceManiac/22c8505d92ef3b228fb41ec9694836ab to your computer and use it in GitHub Desktop.
rough kwargs macro sketch
use std::borrow::Cow;
#[macro_export]
macro_rules! kwargs {
// pass no arguments
() => { |_| {} };
// in-progress variants
(@struct [$($attr:meta)*] $name:ident [$($decls:tt)*] $field:ident: $typ:ty, $($rest:tt)*) => {
kwargs!(@struct [$($attr)*] $name [$($decls)* $field: ::std::option::Option<$typ>,] $($rest)*);
};
// version that does not end with a comma
(@struct [$($attr:meta)*] $name:ident [$($decls:tt)*] $field:ident: $typ:ty) => {
kwargs!(@struct [$($attr)*] $name [$($decls)* $field: ::std::option::Option<$typ>,]);
};
// base case
(@struct [$($attr:meta)*] $name:ident [$($field:ident: $typ:ty,)*] $(,)*) => {
$(#[$attr])*
#[derive(Default)]
pub struct $name<'kw> {
$(pub $field: $typ,)*
__marker: ::std::marker::PhantomData<&'kw ()>,
}
};
// resolve kwargs
(@resolve: $kw:ident) => {
{ let mut a = Default::default(); $kw(&mut a); a };
};
// declare kwargs receiver struct
($($(#[$attr:meta])* struct $name:ident { $($inner:tt)* };)*) => {
$(kwargs!(@struct [$($attr)*] $name [] $($inner)*);)*
};
// pass some arguments, colon variant
($($field:ident: $value:expr),* $(,)*) => {
|x| { $(x.$field = Some(From::from($value));)* }
};
}
// example usage
kwargs! {
#[doc(hidden)]
struct FooArgs { unused: u32, first: Cow<'kw, str>, second: &'kw str };
}
pub fn foo<KW: FnOnce(&mut FooArgs)>(param: u32, kw: KW) {
let kwargs = kwargs!(@resolve: kw);
println!("param: {}", param);
println!(" first: {:?}", kwargs.first);
println!(" second: {:?}", kwargs.second);
}
fn main() {
foo(1, kwargs!(first: "First", second: "Second"));
//foo(2, kwargs!(second = "Second", first = "First".into()));
foo(3, kwargs!(first: "First"));
foo(4, kwargs!(second: "Second"));
foo(4, kwargs!());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment