Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Python自作シリアライズ

 Python自作シリアライズ

C言語の struct や C# の fieldoffset 属性のようなバイナリーシリアライズの方法についての検討。

(とはいえ、共用体のような領域の共有や Fieldoffset のような任意位置へのシークみたいな機能までは考えてなくて、文字列型を含んだクラス(=構造体)のメンバーを、上から順番にバイナリーでシリアライズしていくようなものを想定しています。)

tsuda.a

June 28, 2023
Tweet

More Decks by tsuda.a

Other Decks in Programming

Transcript

  1. どういうこと? • C言語の構造体/共用体や C# の FieldOffset みたいなことがしたい。 • (=メモリマッピングを制御したい) offset

    0 0xf0 long lg (0x12345678abcdef0) int i1 (0x9abcdef0) 1 0xde 2 0xbc 3 0x9a 4 0x78 int i2 (0x12345678) 5 0x56 6 0x34 7 0x12 8 0x18 double d (0x400921fb54442d18) (3.141592653589793) 9 0x2d 10 0x44 11 0x54 12 0xfb char c (0x21fb) 13 0x21 14 0x09 byte b (0x09) 15 0x40
  2. 4. メンバーのアノテーションと値を読み込み for var_name in annots.keys(): # 値の取得 value =

    getattr(hoge, var_name) # アノテーションの取得 annot = annots.get(var_name) # アノテーションのパース m = re.match(r'^(?P<type>[A-Z])(?P<length>[0-9]*)$', annot)
  3. 5. 変換(数値) # short 型(INT16)の値をエンコード if m.group('type') == 'I': result

    += struct.pack('<h', value) # int 型(INT32)の値をエンコード if m.group('type') == 'L': result += struct.pack('<i', value)
  4. 5. 変換(文字列) # sjis string の値をエンコード if m.group('type') == 'C':

    # 指定長を数値化して偶数値に切り上げ length = (int(m.group('length')) + 1) // 2 * 2 # エンコード a = value.encode('Shift-Jis') # 末尾の null padding a += bytes(length) result += a[0:length]
  5. 結果 >>> result b'¥x01¥x00123ABC¥x00¥x00¥x00¥x00¥x02¥x00¥x01¥x00' offset 0 0x01 INT16 a (1)

    1 0x00 2 0x31 Char[10] b ('123ABC') 3 0x32 4 0x33 5 0x41 6 0x42 7 0x43 8 0x00 9 0x00 10 0x00 11 0x00 12 0x02 INT32 c (65538) 13 0x00 14 0x01 15 0x00