I'd like to create a macro that encodes some simple-ish structures into a serialization format like CBOR, at compile time instead of runtime. This saves doing things like vector allocations and some other inefficiencies by automatically calculating size at macro-evaluation time. But it looks like I can't make it generate different code for string literals and integer literals? Or make it generate different code for larger integers? Is there any good way around this? e.g. I wish we had some kind of if!($expr isa INTEGER_LITERAL && $expr < 24){ /* skip the type byte */ }
Also it seems const fn's can't do this either because they can't return differently sized arrays depending on input.
#![feature(trace_macros)]
use std::io::{self, Write};
//Convert an array of u8's to a static array in CBOR format.
//We don't handle numbers > 256 or array elements > 23 at this time.
//Is it possible to have a macro generate one thing if a constant
//literal number is within some bounds? I don't think so.
//Also, we'd love to handle strings and numbers differently. Is that possible?
//Again, I don't think so, not by itself or even using const fn's.
macro_rules! cbor {
(@array $count:expr ; $size:expr ; [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
//more elements
{
io::stdout().lock().write_all(b"next element\n")?;
cbor!(@array ($count + 1) ; ($size + 2) ; [$($elems,)* 24, $next,] $($rest)*)
}
};
(@array $count:expr ; $size:expr ; [$($elems:expr,)*] $next:expr) => {
//last element
{
println!("array done with {} elements, {} bytes", $count + 1, $size + 2);
let a: [u8; ($size + 2)] = [($count + 1) | 0b100_00000, $($elems,)* 24, $next];
a
}
};
([ $($tt:tt)+ ]) => {
//array start
{
io::stdout().lock().write_all(b"starting to process the array\n")?;
cbor!(@array 0 ; 1 ; [] $($tt)+)
}
}
}
fn main() -> io::Result<()> {
trace_macros!(true);
let encoded_array = cbor!([1, 2, 103]);
println!("{:?}", encoded_array);
Ok(())
}
Output:
starting to process the array
next element
next element
array done with 3 elements, 7 bytes
[131, 24, 1, 24, 2, 24, 103]