BCD を取り回すライブラリを Rust で書いた

エンジニアの佐野です。文字列および数値を BCD と相互変換するライブラリを Rust で書きました。

github.com

crates.io にも公開しました https://crates.io/crates/bcd-convert

BCD

BCD は Binary-coded decimal の略で日本語では二進化十進表現などとも呼ばれます。

カンムの業務で言うとクレカ決済のデータを扱っているとたびたび出現します*1。例えばカード決済のデータをやりとりする ISO8583 というプロトコルではカード番号は 0x40, 0x19, 0x24, 0x99, 0x99, 0x99, 0x99, 0x99 のようなバイト列で表現されたりするのですが、このような処理をする際は1バイトの上位4ビットと下位4ビットに現れる数字列を分解して 4019249999999999 と解釈してカード番号を得ます*2

このライブラリを使うと BCD <-> 文字列は次のように相互変換できます。

#[test]
fn test_bcd_to_str() {
    let bcd = BcdNumber(vec![0x40, 0x19, 0x24, 0x99, 0x99, 0x99, 0x99, 0x99]);
    let s = bcd.to_string();
    assert_eq!(s, "4019249999999999");
}

#[test]
fn test_str_to_bcd() {
    let s = "4019249999999999";
    let bcd = s.parse::<BcdNumber>().unwrap();
    assert_eq!(
        bcd,
        BcdNumber(vec![0x40, 0x19, 0x24, 0x99, 0x99, 0x99, 0x99, 0x99])
    );
}

詳しい使い方は Docs.rsGitHub を見ていただくとして、 u64 や [u8] のような生バイト列との相互変換もサポートしています。

なぜ Rust

カンムのメイン言語は Go, TypeScript, Python なのですがたまには新しい言語を学びたくなってくるものです。その一環として自分は Go で書かれた決済システムの一部を Rust で書き換えるという個人プロジェクトを始めました*3。ゴールは Rust への書き換えと私自身の満足です。

チュートリアルを1.5周ほどやったあとに AI に手伝ってもらいながら書いたのですがまだ勘所がわからず四苦八苦している状態です。もっとうまい書き方や「らしい」書き方があるかもしれません。

おわり

*1:このような形式で送受信するケースがある

*2:これはもちろん存在しないカード番号で今後も発行されることもないカード番号です

*3:カンムでは今のところ Rust をプロダクションに導入する計画はなく、あくまでも私が自分の目標のために始めました。忙しくなったを言い訳にして頓挫する可能性もあります。