Rustでビットパターンにマッチさせるマクロを作った
はじめに
前回の記事(Rustで+++を実現する)は完全にネタでしたが、今回は同じく関数呼び出し形式の手続きマクロで実用的なものを作ってみました。
bitpattern!
というマクロで整数型とビットパターンのマッチと抽出ができます。
似たようなマクロで bitpat!
というものがあるのですが、こちらは macro_rules!
によるマクロとなっていて、宣言的なマクロを再帰で呼び出すことで、任意長のビットパターンに対応しています。このため、ビットパターンが長くなると非常に再帰が深くなり(例えば32ビットのパターンで3万以上の再帰呼び出しが発生しました)、実用的にはちょっと厳しいところがありました。
手続きマクロであれば、ビットパターンは普通の文字列処理として扱えるので、長くなっても問題ありません。
そこで、Rust 1.45.0で安定化した関数呼び出し形式の手続きマクロを使って bitpattern!
を実装しました。
使い方
ビットパターンとして使える値は 0
と 1
と ?
と _
が特別な意味を持っていて、それ以外にも任意の文字が使えます。
例えば 0
と 1
を使うと
use bitpattern::bitpattern;
let x = 0xacu8; // 2進数で 10101100
assert_eq!(bitpattern!("1010_1100", x), Some(()));
assert_eq!(bitpattern!("1010_0100", x), None);
のように、ビットパターンがマッチすれば Some(())
が、しなければ None
が返ってきます。
(パターンは_
で区切ることができます)
これだけだと単なる一致比較ですが、 ?
を使うと、0/1どちらにもマッチさせることができます。
let x = 0xacu8; // 2進数で 10101100
assert_eq!(bitpattern!("1?10_1?00", x), Some(()));
let x = 0xe8u8; // 2進数で 11101000
assert_eq!(bitpattern!("1?10_1?00", x), Some(()));
適当な文字を使うと、その部分を抽出することができます。
例えば a
を使って上から2ビット目を抽出した例です。
let x = 0xacu8; // 2進数で 10101100
assert_eq!(bitpattern!("1a101100", x), Some(0));
同じ文字を連続させればその部分がまとめて抽出されます。
let x = 0xacu8; // 2進数で 10101100
assert_eq!(bitpattern!("1aa01100", x), Some(1));
複数の箇所を抽出することも可能です。
抽出箇所が複数の場合タプルで返ってきます。
let x = 0xacu8; // 2進数で 10101100
assert_eq!(bitpattern!("1aa0aa00", x), Some((1, 3)));
抽出箇所が隣接する場合、文字を変えればOKです。
let x = 0xacu8; // 2進数で 10101100
assert_eq!(bitpattern!("1aabbb00", x), Some((1, 3)));
パターンの長さに応じて型はu8
からu128
まで自動的に調整されます。
let x = 0xacf0acf0acf0acf0acf0acf0acf0acf0u128;
assert_eq!( bitpattern!( "1010_1100_1111_0000_1010_1100_1111_0000_1010_1100_1111_0000_1010_1100_1111_0000_1010_1100_1111_0000_1010_1100_1111_0000_1010_1100_1111_0000_1010_1100_1111_0000", x), Some(()));
bitmatch
同じくビットパターンのマッチをlet
やmatch
に対するアトリビュートマクロで実現したbitmatch
というものもあります。
こちらも便利なので、用途に応じて使い分けるといいでしょう。
一緒に使えるように、bitpattern
のパターン記法はこのbitmatch
と合わせてあります。
use bitmatch::bitmatch;
#[bitmatch]
fn decode(inst: u8) -> String {
#[bitmatch]
match inst {
"00oo_aabb" => format!("Op {}, {}, {}", o, a, b),
"0100_aaii" => format!("Val {}, {}", a, i),
"01??_????" => format!("Invalid"),
"10ii_aabb" => format!("Ld {}, {}, {}", a, b, i),
"11ii_aabb" => format!("St {}, {}, {}", a, b, i),
}
}
Author And Source
この問題について(Rustでビットパターンにマッチさせるマクロを作った), 我々は、より多くの情報をここで見つけました https://qiita.com/dalance/items/7c03706741eacc058785著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .