I wrote a higher order macro to apply another macro to a range of values 0..n
where n
is an octal number with digits separated by spaces. It's primarily useful for generating impls on arrays.
The macro:
macro_rules! map_range {
/* The actual macro */
(%# apply $tmpl:ident, $shift:expr, $offset:expr, $by:expr, (0 $($rest:tt)*)) => {
map_range!(%# apply $tmpl, $shift, $offset, $by*2, ($($rest)*));
map_range!(%# apply $tmpl, $shift, $offset + $by, $by*2, ($($rest)*));
};
(%# apply $tmpl:ident, $shift:expr, $offset:expr, $by:expr, (1 $($rest:tt)*)) => {
map_range!(%# apply $tmpl, $shift-$by, $offset, $by, (0 $($rest)*));
$tmpl!((($offset) - ($shift)));
};
(%# apply $tmpl:ident, $shift:expr, $offset:expr, $by:expr, ()) => { };
/* Convert from little endien octal to big endian binary */
(%# convert $tmpl:ident, (0 $($octal:tt)*), ($($binary:tt)*)) => {
map_range!(%# convert $tmpl, ($($octal)*), (0 0 0 $($binary)*));
};
(%# convert $tmpl:ident, (1 $($octal:tt)*), ($($binary:tt)*)) => {
map_range!(%# convert $tmpl, ($($octal)*), (1 0 0 $($binary)*));
};
(%# convert $tmpl:ident, (2 $($octal:tt)*), ($($binary:tt)*)) => {
map_range!(%# convert $tmpl, ($($octal)*), (0 1 0 $($binary)*));
};
(%# convert $tmpl:ident, (3 $($octal:tt)*), ($($binary:tt)*)) => {
map_range!(%# convert $tmpl, ($($octal)*), (1 1 0 $($binary)*));
};
(%# convert $tmpl:ident, (4 $($octal:tt)*), ($($binary:tt)*)) => {
map_range!(%# convert $tmpl, ($($octal)*), (0 0 1 $($binary)*));
};
(%# convert $tmpl:ident, (5 $($octal:tt)*), ($($binary:tt)*)) => {
map_range!(%# convert $tmpl, ($($octal)*), (1 0 1 $($binary)*));
};
(%# convert $tmpl:ident, (6 $($octal:tt)*), ($($binary:tt)*)) => {
map_range!(%# convert $tmpl, ($($octal)*), (0 1 1 $($binary)*));
};
(%# convert $tmpl:ident, (7 $($octal:tt)*), ($($binary:tt)*)) => {
map_range!(%# convert $tmpl, ($($octal)*), (1 1 1 $($binary)*));
};
(%# convert $tmpl:ident, (), $binary:tt) => {
map_range!(%# apply $tmpl, 0, 0, 1, $binary);
};
/* Public API */
($tmpl:ident @ $($num:tt)*) => {
map_range!(%# convert $tmpl, ($($num)*), ());
};
}
Example:
use std::mem;
trait AsArray<T> {
fn as_array(&self) -> &T;
}
macro_rules! array_impl {
($value:expr) => {
impl<T> AsArray<[T; $value]> for [T] {
fn as_array(&self) -> &[T; $value] {
const LEN: usize = $value;
if self.len() == LEN {
unsafe { mem::transmute(self.as_ptr()) }
} else {
panic!();
}
}
}
};
}
map_range!(array_impl @ 4 0 0); // Call array_impl!(i) for i in 0..256
So, before I create an entirely new crate for this macro, are there any macro collection crates where this might belong?