Skip to content

Instantly share code, notes, and snippets.

@Limeth
Created July 28, 2016 20:02
Show Gist options
  • Save Limeth/be6fc7b2549251e7d691731e6442827b to your computer and use it in GitHub Desktop.
Save Limeth/be6fc7b2549251e7d691731e6442827b to your computer and use it in GitHub Desktop.
#[macro_export]
#[doc(hidden)]
macro_rules! define_msg_internal {
(@as_item $i:item) => ($i);
(@gen_match $f:ident, $l:ident; $($lang:pat => $format:tt),*; $tail:tt) => (
match $l {
$($lang => define_msg_internal!(@gen_arm $f; $format; $tail),)*
}
);
(@gen_arm $f:ident; $format:tt; ($($tail:tt)*)) => (
write!($f, $format $($tail)*)
);
(
$name:ident
($($prefix:tt)*)
{
constr: [ $($constr:tt)* ],
params: [ $($params:tt)* ],
$($_generics:tt)*
},
$({
$($fname:ident: $ftype:ty),* $(,)*
})*:
$($lang:pat => $format:tt),* $(,)*
) => (
// since `$($constr)*` and `$($params)*` have to be expanded lazily,
// we need to coerce the AST to delay the expansion
define_msg_internal! { @as_item
#[derive(Debug)]
$($prefix)* struct $name<$($constr)*> {
$($(pub $fname: $ftype,)*)*
}
}
define_msg_internal! { @as_item
impl<$($constr)*> $crate::Localize for $name<$($params)*> {
fn fmt_localized(&self, f: &mut ::std::fmt::Formatter,
lang: &str) -> ::std::fmt::Result {
// "tt bundling" as in http://stackoverflow.com/a/37754096
define_msg_internal!(@gen_match f, lang;
$($lang => $format),*;
($($(, $fname = $crate::Localized::new(&self.$fname, lang))*)*))
}
}
}
);
}
#[macro_export]
macro_rules! define_msg {
($(#[$meta:meta])* pub $name:ident $($t:tt)*) => (
parse_generics_shim! {
{ constr, params, ltimes, tnames },
then define_msg_internal!($name ($(#[$meta])* pub)),
$($t)*
}
);
($(#[$meta:meta])* $name:ident $($t:tt)*) => (
parse_generics_shim! {
{ constr, params, ltimes, tnames },
then define_msg_internal!($name ($(#[$meta])*)),
$($t)*
}
);
}
// example usage
define_msg! { pub SomeError<'a> { s: &'a str }:
"en" => "some error with {s}",
_ => "(insert a generic message for some error with {s})",
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment