バイナリデータをいい感じに作成するツールを作成する
はじめに
独自のプロトコルや特定の目的の実験のためにバイナリデータを作成するツールを作成したため、その使い方をざっくりと紹介する。ただし、現状はまだまだ雑な部分は多いし、単体テストの正常系レベルのテストしかしていないことに注意してもらいたい。
記事執筆時点でのソースコードは以下に公開している。
基本的な作成方法
今回作成したツールによりバイナリファイルを生成するとき、事前に以下の準備が必要となる。
バイナリファイルのフォーマットの定義が記述されたXMLファイル
バイナリファイルに設定する値が列挙されたヘッダ付きのCSVファイル
例えば、XMLファイルであれば、以下のように与える。
ここで、format.xsd
はこのようなXMLでどのようなフォーマットが記述できるのかを示したXMLスキーマであり、どのような記述が可能であるかについてはこれを参照することでも確かめることができる。また、Red Hatが開発しているVSCode上での拡張を利用すれば入力の候補が出現するためフォーマットの定義は容易になるだろう。
例えば、CSVファイルについては、以下のようにヘッダ付きで与える。今回の場合であれば、上記で示したXMLの//item/[@name='名称']
に以下のCSVの対応するvalue
がディスパッチされ、バイナリファイルとして出力される。
実際にバイナリファイルを生成する際は、以下のようなコマンドで生成をすることが出来る(とりあえず動けばいいということでコマンドライン引数の解析はかなり雑である)。
他のコマンドライン引数としては、-g キー 値
と入力することで外部からあたかも環境変数のような特別な入力値を設定することができる。
以下では、ユースケース別の基本的なバイナリファイルの作成方法を示していく。なお、今回は結果を見やすくするためにテキストとして読むことが可能なファイルのみを出力するようにする。
単純な値の出力
まずは、単純に指定した値を出力する方法を示す。以下にバイナリファイルのフォーマットであるXMLファイルを示す。
次にディスパッチを行うCSVファイルを示す。
バイナリファイルを生成する際のコマンドを以下に示す。
このとき生成されるバイナリファイルの中身は以下のようになっている。
固定長項目の出力
一般にバイナリファイルで出力される基礎となるのはバイト数が固定長の項目である。固定長項目は単にバイト数を固定長にするだけではなく、不足しているバイト数分を埋めるパディングを指定することが多いだろう。例えば、テキスト形式の数値であれば0パディングであったり、通常の文字列であればnullパディングなどを行ったりするだろう。以下にそれを行うためのバイナリファイルのフォーマットであるXMLファイルを示す。
今回の場合、全ての値をdefualt-value
でデフォルト値が設定されるようにしているため、CSVファイルは省略する。バイナリファイルを生成する際のコマンドを以下に示す。
このとき生成されるバイナリファイルの中身は以下のようになっている。ちゃんと固定長でかつパディングが正常に働いていることがわかるだろう。
一般の可変長項目の出力
一般にバイナリファイルでは可変長のデータを出力する際はその項目長を出力する。そのような機能の実現のためにXPathを利用した値の出力をサポートしている。以下にそれを行うためのバイナリファイルのフォーマットであるXMLファイルを示す。ポイントとしては、//item/@eval
でlazy
を指定していることである。これは遅延評価を行うための指定であり、これとXPathの評価を合わせることにより、かなり自由度の高い表現を行うことができる。
次にディスパッチを行うCSVファイルを示す。
バイナリファイルを生成する際のコマンドを以下に示す。
このとき生成されるバイナリファイルの中身は以下のようになっている。値1
はUTF-8で4バイト、バイナリファイルの全長が12バイトのデータになるため、正しく項目長が出力できていることがわかる。
繰り返し項目の出力
バイナリデータ中のリストデータの出力のためには繰り返し項目が出力できるような仕組みが必要である。そのような機能の実現のためにrepeat
タグを利用した値の出力をサポートしている。以下にそれを行うためのバイナリファイルのフォーマットであるXMLファイルを示す。
次にディスパッチを行うCSVファイルを示す。
バイナリファイルを生成する際のコマンドを以下に示す。
このとき生成されるバイナリファイルの中身は以下のようになっている。値1
から順に値5
と出力できているため、繰り返し項目が正しく出力できていることがわかる。
文字の変換
入力された文字を適当に変換したりして加工したものを出力したいこともあるだろう。そのような機能の実現のために、入力値を変換する規則をサポートしている。以下にそれを行うためのバイナリファイルのフォーマットであるXMLファイルを示す。
chara-map.xml
は変換に用いる変換の定義が記載されたXMLファイルであり、以下のようなfrom
とto
による変換規則が記載されている。
次にディスパッチを行うCSVファイルを示す。
バイナリファイルを生成する際のコマンドを以下に示す。
このとき生成されるバイナリファイルの中身は以下のようになっている。chara-map.xml
で示した通りの変換規則で出力できていることがわかる。
応用
実用的なものではないが、応用すればこういったこともできるという一例を示す。まぁ、ほぼほぼXPathによる計算の効果なだけではあるが。
FizzBuzz
XMLファイル
CSVファイル
出力結果
フィボナッチ数列の計算
XMLファイル
CSVファイル
出力結果
おわりに
今回実装したツールが持つ機能は今回紹介したもの以外にも割とたくさんある。とはいえ、面倒と思って作成していない機能もある。代表例として挙げるとすれば、バイナリファイルからCSVへ変換する機能である。一応、直ちに拡張できるようには作ってあるが、バイナリ値を逆変換して文字列値に起こすのが面倒(特にパディングの除去回りはどうしても不完全性をもつためルール作りから始める必要がある)だし、私は使う予定は今のところないので作成していない。
現状でもそれなりに複雑なデータが作成することができるため、テスト用のアプリケーションに組み込むなどしても有効に働くかもしれない。そのうち、いくつかのプロトコルのフォーマットのXMLを作成するのもいいかもしれない。