Rust で [u8; n] から数値を復元する
ビットシフトでもだいじょうぶ
最近 Rapberry Pi などからセンサー類を起動して遊ぶということをしています。
そういうモジュール類から得られるデータは基本的に単なる u8
の配列です。したがって、指定された型に戻す必要があります。
指定された型が u8
を超える範囲の数値の場合、ビットシフトを使って復元します。
let received: [u8; 2] = [0xf2, 0xf4];
println!("{}", (received[0] as u16) << 8 | received[1] as u16);
// => 62196
ビットシフト自体は話が簡単なのですが、もとが u8
なので Rust ではオーバーフローが指摘され、キャスティングなしにコンパイルができません。
println!("{}", received[0] << 8 | received[1]);
// 6 | println!("{}", received[0] << 8 | received[1]);
// | ^^^^^^^^^^^^^^^^ attempt to shift left with overflow
型キャスティングが必要になると演算子の優先順位から ()
も必要となり、コードのみためが多少煩雑になります。
from_be_bytes
そこでその煩雑さから逃れつつ、簡単に狙ったバイト長の数値に変換するための from_be_bytes
というメソッドが数値型に用意されています。
let received: [u8; 2] = [0xf2, 0xf4];
println!("{}", u16::from_be_bytes(received));
// => 62196
println!("{}", i16::from_be_bytes(received));
// => -3340
これで演算子の優先順位に悩まされることなく、安全に望む数値を手に入れることができます。
余談
実際の処理では 3 bytes 中の真ん中のバイトの上下 4 ビットが 1 バイト目と 3 バイト目の下位ビットにあたるようなことがあり、ビットシフト自体からは離れられないようです。