问题
I'm trying to learn the Rust macro system by writing a simple macro that generates a struct based on some unsigned integer type (u8
, u16
, u32
, u64
). I want something like this:
bitmessage! {
struct Header(u16);
version: 8, 5; // the first number is the length, second is value
data: 8, 5;
}
To be more specific, I'm looking for some way to store certain information in an unsigned integer type with various offsets. One use case is to read some bytes and construct some kind of "message":
[ 15 14 13 12 11 10 09 08 | 07 06 05 04 03 02 01 01 ]
The higher part of the message contains some data/information, the lower part a versioning field. (This is just a toy example).
This is my effort so far, but the inner repeating expansion does not compile:
macro_rules! bitmessage {
(struct $name:ident($n:ty);
$($field_name:ident: $length:expr, $value:expr;)*) => {
struct $name ($n);
$($name.1 = $name.1 | $value << $length)*
};
}
One solution could be to store the relevant bytes in a struct, implementing it directly (or with a trait) to get the appropriate fields, but this would involve too much bit-shifting logic (no problem with that, but there must be a more convenient way).
I am aware of bitflags and bitfield. Neither of them matches my use case.
回答1:
You cannot evaluate expressions in a macro. Macros only create, remove, or move around parts of the input code's abstract syntax tree (AST). No evaluation occurs during macro expansion (even the name "expansion" is a hint).
The best you can do is create code that can be evaluated at compile time, after the macros have been expanded. The subset of code that is valid at compile time is limited, but it will grow in the future.
For your specific example, it's very unclear what you want the result of the macro to be. Remember that macros don't have the ability to "make up" new Rust concepts, they only allow you to express existing repeated concepts with fewer characters.
Because of this, I always recommend that people write out the first two repeated cases fully. This forces you to write the full valid Rust code and identify the differences between them. You can then extract the commonality using any normal Rust technique.
See also:
- The Little Book of Rust Macros
- Is there a way to count with macros?
来源:https://stackoverflow.com/questions/49576878/how-do-i-evaluate-expressions-in-rusts-macro-system