Skip to content

Instantly share code, notes, and snippets.

@tesaguri
Created December 4, 2018 00:59
Show Gist options
  • Save tesaguri/77f8ae01ceffd4fb625078b89a08ad86 to your computer and use it in GitHub Desktop.
Save tesaguri/77f8ae01ceffd4fb625078b89a08ad86 to your computer and use it in GitHub Desktop.
Defining pseudo custom attributes in a macro
macro_rules! request {
(
@parsing $(#[$attrs:meta])*; #[get($uri:expr)] $(#[$rest_attrs:meta])*
struct $Name:ident;
$($rest:tt)*
) => {
request! {
@GET($uri)
$(#[$attrs])*
$(#[$rest_attrs])*
struct $Name;
$($rest)*
}
};
(
@parsing $(#[$attrs:meta])*; #[post($uri:expr)] $(#[$rest_attrs:meta])*
struct $Name:ident;
$($rest:tt)*
) => {
request! {
@POST($uri)
$(#[$attrs])*
$(#[$rest_attrs])*
struct $Name;
$($rest)*
}
};
(@parsing $(#[$attrs:meta])*; #[$attr:meta] $($rest:tt)*) => {
request! { @parsing $(#[$attrs])* #[$attr]; $($rest)* }
};
(@parsing $(#[$attrs:meta])*; struct $Name:ident { $($body:tt)* }) => {
compile_error!("expected URI");
};
(
@$method:ident($uri:expr)
$(#[$attrs:meta])*
struct $Name:ident;
$($rest:tt)*
) => {
$(#[$attrs])*
struct $Name;
impl $Name {
fn method() -> &'static str {
stringify!($method)
}
fn uri() -> &'static str {
$uri
}
}
request! { $($rest)* }
};
(@ $($arg:tt)*) => {
compile_error!(concat!(
"invalid macro invocation: foo! { @ ",
stringify!($($arg)*),
));
};
($($body:tt)+) => {
request! { @parsing; $($body)* }
};
() => {};
}
request! {
#[derive(Clone)]
#[get("https://example.com/get")]
struct Get;
#[post("https://example.com/post")]
struct Post;
}
fn main() {
let _ = Get.clone();
assert_eq!(Get::method(), "GET");
assert_eq!(Get::uri(), "https://example.com/get");
assert_eq!(Post::method(), "POST");
assert_eq!(Post::uri(), "https://example.com/post");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment