I have been playing with Rust for a while and decided it is time to start with macros. I want to create a macro that allows for a bitwise and operation on specific bits of unsigned integer variables. Here is what I currently have which is working:
macro_rules! AND {
($($val:ident.$bit:literal), *) => {
{
let mut val_out = 0x01;
$(
val_out &= ($val >> $bit);
)*
val_out & 0x01
}
};
}
fn main() {
let x = 0x01;
let y = 0x02;
let z = 0x10;
println!("{}", AND!(x.0, y.1, z.4)); // Prints 1
println!("{}", AND!(x.0, y.1, z.0)); // Prints 0
}
What I want to do is also allow for a negation operator. This is what I have that compiles, but I cannot figure out how to determine if the exclamation point was matched or not.
macro_rules! AND {
($($(!)?$val:ident.$bit:literal), *) => {
{
let mut val_out = 0x01;
$(
val_out &= ($val >> $bit);
)*
val_out & 0x01
}
};
}
fn main() {
let x = 0x01;
let y = 0x02;
let z = 0x10;
println!("{}", AND!(!x.0, !y.1, z.4)); // Prints 1, would like to print 0
println!("{}", AND!(x.0, y.1, !z.0)); // Prints 0, would like to print 1
}
I have tried to match an expression instead of the exclamation point, but expressions have to be the last thing matched. I also tried to match an ident after the literal, with the idea that an underscore after the literal could denote negation, but when I used an if or match statement to determine if the ident was matched, I get an error:
macro_rules! AND {
($($val:ident.$bit:literal$($negate:ident)?), *) => {
{
let mut val_out = 0x01;
$(
if $negate == "_" {
val_out &= (!$val >> $bit);
}
else {
val_out &= ($val >> $bit);
}
)*
val_out & 0x01
}
};
}
fn main() {
let x = 0x01;
let y = 0x02;
let z = 0x10;
println!("{}", AND!(x.0, y.1, z.4_));
error: variable 'negate' is still repeating at this depth
--> src/main.rs:8:20
|
8 | if $negate == "_" {
| ^^^^^^^
Any ideas would be appreciated. Thanks!