RustにいればRustに従え(2) CRC8をmut無、for無で計算する

Joseph Halfmoon

Rust言語では書き換え可能な変数には mut と宣言しないとなりません。使っちゃいけないわけじゃないけれども。前回はmut無、for無で数値積分をやっつけました。今回はmut無、for無でCRC8を計算してみます。結局、mutの代わりにクロージャ、forの代わりにイテレータが暗躍?しているのだけれども。

※『RustにいればRustに従え』関係記事 index はこちら

※動作確認は、Windows11のWSL2上にインストールしたUbuntu20.04LTS上のrustc 1.64.0 (a55dd71d5 2022-09-19) で行っています。

トートツにCRC8(サイクリック・リダンダンシー・コード)

唐突にCRC8をやってみましたが、別シリーズの以下記事でPython3で書いたAHB21Bセンサ向けのスクリプトが元になってます。

部品屋根性(77) AHT21B、CRC8でのデータ検査を追加。ラズパイPython

上記ではRasberry Pi 3 model B+のI2CにAHB21B温湿度センサを接続して温度、湿度を読み取っているのです。そのセンサ・データの検証用にCRC8が使われていたのです。CRC8にもいろいろあり、ということで生成多項式はセンサで一般的じゃないかと思われる(個人の感想です)Dallas-Maxim式です。

手ごろな動作確認用の入力データとCRC8の計算結果が欲しかったので、以下のサイトを使わせていただきました。自由自在?に各種CRCを計算できるもの。あざーす。

CRC Calculator (Javascript)

Rustで書き直したコード

元Python3の関数をRustで書き直したものが以下に。前回につづいてVecを使ってしまっているところがカッコ悪い感じがするのであります(どおしたらええんじゃ?)が、mut宣言無、forループ無のコードですじゃ。

fn crc8u8(bint: u8, poly: u8) -> u8 {
    let lis: Vec<u8> = (0..8).collect();
    lis.iter().fold(bint, |crc, _x| if (crc & 0x80) == 0x80 {(crc << 1) ^ poly} else {crc << 1})
}

fn main() {
    let testpat: [u8; 4] = [0x30, 0x31, 0x32, 0x33]; //"0123"
    let poly: u8 = 0x31; // Dallas-Maxim CRC8
    let init: u8 = 0xFF;
    let crc8: u8 = testpat.iter().fold(init, |crc, x| crc8u8(crc ^ x, poly));
    println!("crc8: 0x{:02x}", crc8);
}ま

crc8u8関数は1バイト分の処理を行う関数です。その中と呼び出し側の両方で iner().fold()を使っており、これで2重のforループ相当の処理をしてます。またイテレータのfold()関数内でクロージャを使うことで明示的なmut宣言無に、途中経過を保持させてます。

Rust風味にはしてみた?けれども、まだまだじゃね。

処理結果

実行結果が以下に。rust_run

上記のCRC計算サイトにて、CRC-8、Custom設定

    1. Polynomial: 0x31
    2. Initial Value: 0xFF
    3. Final Xor Value: 0x0
    4. CRC Input Data(Byte): 0x30 0x31 0x32 0x33

で計算したところ、計算結果0xF9を得ました。計算結果はあってるみたいね(一例だけじゃないか、手抜きだな自分。)

RustにいればRustに従え(1) ∫[0:1]1/(1+x^2)dxをRustで解く へ戻る

RustにいればRustに従え(3) 移動平均をmut無、for無で計算。表示にfor使用 へ進む