Skip to content

Instantly share code, notes, and snippets.

@yfakariya
Last active September 4, 2015 11:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yfakariya/fb6d5c66fa4d8a82346b to your computer and use it in GitHub Desktop.
Save yfakariya/fb6d5c66fa4d8a82346b to your computer and use it in GitHub Desktop.
Spec draft for embedding type information

Purpose 目的

Make .NET to .NET serialization more easily by embedding type information. Interoperability should be considered as possible. 型情報を埋め込むことで、.NET どうしのシリアライズをもっと楽にする。相互運用性は可能な限り考慮されるべき。

Usecase ユースケース

  1. Serialize polimorphic collection (issue #58) ポリモーフィックなコレクションをシリアライズする
  2. Serialize 'rich' domain model which has own data and logic (issue #47) 固有のデータとロジックを持つ「リッチな」ドメインモデルをシリアライズする

Basic design 基本的な設計

  • Serialize object's type information with its values. オブジェクトの型情報を値と一緒にシリアライズする。
  • The type information and values are serialized within an array. 型情報と値は 1 つの配列内にシリアライズする
  • The type information is indicated as marker ext type library defined type, its type code is 0. 型情報は型コード 0 のマーカー extlibrary defined type で示される。
  • The type information itself is encoded in an array, and its schema is defined by the value of the library defined type. 型情報そのものは配列としてエンコードされ、そのスキーマは、library defined type の値で決まる。
  • The type information can be numeric value for closed & known set of types. It acts as "type code". 閉集合で既知の型しかない場合に型情報は数値にできる。この場合、型情報は「型コード」としてふるまう。

Proposals 提案

Encode typed values as follows: 型付の情報は以下のようにエンコードする。

[ext(type information), array|map(serialized value)]

The ext type value consists of 2 element array. The 1st element is subcode of the type info. For examble, in MessagePack for CLI implementation, the value 0 indicates the 2nd element contains "type code" for the value. Else, the value 1 indicates the 2nd element contains native type information (described bellow). ext 型の値は 2 要素の配列からなる。1 番目の要素は型情報のサブコードである。たとえば、MessagePack for CLI の実装では、値 0 は 2 番目の要素が値の「型コード」であることを示す。それに対し、値 1 は 2 番目の要素がネイティブ型情報(後述)を含むことを示す。

Pros 利点

  • Easy to encode and decode. Encoder can emit ext without calculating bytes length of variable lentgh serialized value (type information should not be so long, thus it is not hard to implement efficiently). Decoder which does not want to interpret type information can skip opaque type info using array handling logic. エンコードとデコードが楽。エンコーダは可変長のシリアライズされる値のバイト長を計算せずに ext を出力できる(型情報はそれほど長くならないはずなので、効率的な実装は難しくないはず)。型情報を解釈したくないデコーダは、配列処理のロジックを使用して、自分が知らない型情報をスキップできる。

Const 欠点

  • It looks unnatural, some people might argue that all values should be encoded in the ext type. 見た目が不自然。ext 型にすべての値をエンコードすべきという主張もあるかもしれない。

Implementation in MessagePack for CLI MessagePack for CLIでの実装

Native Type Information ネイティブ型情報

In CLI(.NET/Mono), the type information consists of 5 required components and 1 optional components. 1) A full name of the type (a name of the type including its namespace); 2) A simple name of the assembly (a name of the libraries, mostly file name without its extension); 3) A version of the assembly, it consists of four 16bit unsigned integers; 4) A culture(locale) of the assembly; 5) A public key or its tokenized representation to distinguish assemblies which have same simple name, it might be null; 6) An optional CPU architecture of the assembly, it actually can be ignored for this context. They can be encoded comma separted string ("Assembly Qualified Type Name"), but it has some redanduncy. So, Native Type Information encodes these values in msgpack format as follows: CLI(.NET/Mono)では、型情報は 5 つの必須コンポーネントと 1 つの省略可能コンポーネントからなる。1) 型の完全名(名前空間を含む型の名前)。2) アセンブリの単純名(ライブラリの名前、ほとんどの場合は拡張子抜きのファイル名)。3) アセンブリのバージョン、4 つの 16 ビット符号なし整数でなる。4) アセンブリのカルチャ(ロケール)。5) 同じ単純名を持つアセンブリを区別するための公開キーまたはそのトークン化表現、null の場合がある。6) 省略可能なアセンブリの CPU アーキテクチャ、今回は無視できる。これらはカンマ区切り文字列(「型のアセンブリ修飾名」)でエンコードできるが、やや冗長である。そのため、ネイティブ型情報としてこれらの値を msgpack フォーマットでエンコードする。

  • It is 5 element array (fixed array 5). まず、これは 5 要素の配列(fixed array 5)である。
  • 1st element is a type full name (str/raw). 1 番目の要素は型の完全名(str/raw)。
  • 2nd element is an assembly simple name (str/raw). 2 番目の要素はアセンブリの単純名(str/raw)。
  • 3rd element is an assembly version, it will be encoded in 4 element array (fixed array 4), and their types are integer. 3 番目の要素はアセンブリのバージョンで、4 要素の配列(fixed array 4)でエンコードされ、その要素型は整数。
  • 4th element is an assembly culture (str/raw). The "neutral" culture will be encoded as nil. 4 番目の要素はアセンブリのカルチャ(str/raw)。「neutral」カルチャは nil としてエンコードされる。
  • 5th element is an assembly public key token (bin). Note that it is not whole public key to reduce its size. The "null" public key token will be encoded as nil. 5 番目の要素はアセンブリの公開キートークン(bin)。サイズを削減するために公開キー全体ではないことに注意。「null」公開キートークンは nil としてエンコードされる。

Specifying Type Information Encoding 型情報エンコードの指定方法

Type embeded field/property must be marked with custom attribute as following 型が埋め込まれたフィールド/プロパティは以下のようにカスタム属性でマークしなければならない。

// For closed known types, it is compact and easy to interop.
// All mappings must be determined in compile time.
[MessagePackKnownType( 0, typeof( FileInfo ) )]
[MessagePackKnownType( 1, typeof( DirectoryInfo ) )]
public FileSystemInfo Info { get; set; }

// For opened, it is easy to use but redandunt and hard to interop.
[MessagePackRuntimeType]
public object Data { get; set; }

Considering Collections and Tuples コレクションとタプルの考慮

As you notice, above code is ambigous for collections. For example, if the attribute used for a property which type is collection type IList<object>, both of the container and the items may have type information. To solve this problem, MessagePack for CLI defines additional attributes like MessagePackKnownCollectionItemTypeAttribute, MessagePackKnownDictionaryKeyTypeAttribute, MessagePackRuntimeCollectionItemTypeAttribute, and MessagePackRuntimeDictionaryKeyTypeAttribute. These are applied for the items or keys of the collections. And, as you imagine, MessagePackKnownTypeAttribute and MessagePackRuntimeTypeAttribute specifies that the collection itself should have type information, not for the keys nor items. 気付いたかと思うが、上記のコードはコレクションの場合にあいまいである。たとえば、コレクション型 IList<Object> のプロパティに対して属性を使用した場合、コンテナと項目の両方が型情報を持ちうる。この問題を解決するため、MessagePack for CLI は MessagePackKnownCollectionItemTypeAttributeMessagePackKnownDictionaryKeyTypeAttributeMessagePackRuntimeCollectionItemTypeAttributeMessagePackRuntimeDictionaryKeyTypeAttribute という追加の属性を定義している。これらはコレクションの項目やキーに適用される。そして、ご想像のように、MessagePackKnownTypeAttributeMessagePackRuntimeTypeAttribute は、コレクション自身が型情報を持つべきこと示すのであり、キーや項目が持つことを示さないのである。

In addition, there is a problem for the tuple. How do you specify which item(s) of the tuple should have type information? To solve this, MessagePack for CLI defines MessagePackKnownTupleItemTypeAttribute and MessagePackRuntimeTupleItemTypeAttribute, they requires the number of the item to be applied. さらに、タプルについても問題がある。タプルのどの項目が型情報を持つのかをどうやって指定すればよいのだろうか。これを解決するために、MessagePack for CLI は MessagePackKnownTupleItemTypeAttributeMessagePackRuntimeTupleItemTypeAttribute を定義しており、これらは適用先の項目の番号を受け取る。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment