Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

Rubyでバイナリデータを格好良く扱うgem「BinData」が素晴らしすぎて膝から崩れ落ちた

0x1234567890abcdef

とてな感じのバイナリデータがあったとします。*1
これを適正に振り分ける場合、どうしてますか?
これまでの私だと、文字列のまんま

val_a = "1234567890abcdef"[10].chr

とやるなり、unpackで配列化して

val_a = "ab".unpack("CC")[0].chr

とやるなりしてました。
ただ、これだと32bitの時の扱いが面倒ですよね。
その上、可変長の場合は専用のロジックを組む必要がある。
しかも途中でセンサの仕様が変わって入り組んだメソッドチェインを解す過程で発狂しそうになったりした事も……。
そんな貴方や私の悩みを解決してくれるのが、今回紹介するGem「BinData」です。

導入

$ gem install bindata

使い方

require 'bindata'

class Sample < BinData::Record
  uint8be  :val_a
  uint8be  :val_b
  uint16be :val_c 
  string   :str, :read_length => 11
  uint8be  :val_end
end 

p source = "1234567890abcdef"
s = Sample.read(source)
p s

"1234567890abcdef"
{:val_a=>49, :val_b=>50, :val_c=>13108, :str=>"567890abcde", :val_end=>102}

となります。

しばらく研究してみたら、
現在のプロジェクトや今後発生する修正案件で相当楽ができそうです(白目

【補足】SerialPortで読んだら「¥u0012¥x9a」みたいなのが出てパースできないんだけど??というとき

8進数リテラルや16進数リテラルが混在した文字列を元の16進数な文字列に置換する - Bye Bye Moore

*1:9の次はaなんですが、こういうデータを渡されたので私の責任ではありません