バックグラウンド:
私は F# Records をよく利用しています。現在、私は独自のバイナリ プロトコル (非常に奇妙に設計されたプロトコル) のパケット分析と再生のプロジェクトに取り組んでいます。
パケットのスケルトン レコードを定義します。
type bytes = byte array
type packetSkeleton = {
part1 : bytes
part2 : bytes
... }
これを使用してパケットを「分析」するのは簡単です (実際には、バイト フィールドに名前を付けるだけです)。
let dissect (raw : bytes) =
let slice a b = raw.[a..b]
{ part1 = slice 0 4
part2 = slice 4 5
... }
これは、長いパケットでも完全に機能します。スライスに予測可能なパターンがある場合は、きちんとした再帰関数を使用することもできます。
そこで、パケットを分析し、必要なフィールドを取り出して、分析から取得したフィールドを使用して packetSkeleton に基づいてパケットを作成します。
let createAuthStub a b c d e f g h ... =
{ part1 = a; part2 = b
part3 = d; ...
}
次に、入力されたスタブを作成した後、ネットワークに配置できる形式にデシリアライズする必要があります。
(* packetSkeleton -> byte array *)
let deserialise (packet : packetSkeleton) =
[| packet.part1; packet.part2; ... |]
let xab = dissect buf
let authStub = createAuthStub xab.part1 1 2 xab.part9 ...
deserialise authStub |> send
したがって、レコード タイプ、特定のパケットのレコードの作成、およびデシリアライズされたバイト配列の 3 つの領域があることになります。コードの明瞭さの点で、これは私のデザインの選択としては不十分であることがわかります。この初期段階でも、すでに足を撃ち始めているのを感じています.
質問:
a) そのようなプロジェクトに正しいデータ型を使用していますか? 私のアプローチは正しいですか?
b) このコードをきれいに感じさせるのをあきらめるべきですか?
これをタッチアンドゴーでコーディングしているので、いくつかの洞察をいただければ幸いです。
PS この問題は C に非常に適していると思いますが、F# の方が楽しいです (さらに、後でディセクタを検証するのも魅力的です)。