AMF0

AMF(ActionScript Message Format) とは Flash などでデータのやりとりに用いられているフォーマットらしく、 AMF0 と AMF3 のバージョンがあります。

ここでは AMF0 の仕様について、英文を適当に読んでにそれっぽく解釈したものを記述していきます。

基本的なデータ単位

U8
符号なし 8 ビットのデータ
U16
符号なし 16 ビット(ビッグエンディアン)のデータ
U32
符号なし 32 ビット(ビッグエンディアン)のデータ
DOUBLE
IEEE 754 の倍精度浮動小数点数(ビッグエンディアン)のデータ
UTF8-char
UTF-8エンコードされた 1 文字のデータ。 1 バイトとは限らない
UTF-8 = U16 *(UTF8-char)
UTF-8エンコードされた文字列。文字列部分のバイト数を U16 で指定する
UTF-8-empty = U16
長さ 0x0000 の空文字列
UTF-8-long = U32 *(UTF8-char)
長くても大丈夫なようにした文字列
value-type
データ(後述)

パケットの構造

AMF0 のデータ単位であるパケットは以下の構造になっています。

amf-packet   = version header-count *(header-type)
               message-count *(message-type)
header-type  = header-name must-understand header-length value-type
message-type = target-uri response-uri message-length value-type

省略した version = U16 などと一緒に整理すると、

  • バージョン = U16
    • AMF0 の場合 0x00 00
  • ヘッダ数 = U16
  • ヘッダ
    • ヘッダ名 = UTF-8
    • must-understand フラグ = U8
      • 0x00 なら false 、 0x00 以外なら true
    • ヘッダ長 = U32
    • ヘッダデータ = value-type
  • ヘッダ数だけヘッダの繰り返し
  • メッセージ数 = U16
  • メッセージ
    • ターゲット URI = UTF-8
    • レスポンス URI = UTF-8
    • メッセージ長 = U32
    • メッセージデータ = value-type
  • メッセージ数だけメッセージの繰り返し

value-type

value-type には数値や配列など任意のデータを記述できるものです。

value-type        = number-type | boolean-type | string-type |
                    object-type | null-type | undefined-type |
                    reference-type | ecma-array-type |
                    strict-array-type | date-type | long-string-type |
                    xml-document-type | typed-object-type

number-type       = 0x00 DOUBLE
boolean-type      = 0x01 U8
string-type       = 0x02 UTF-8
object-type       = 0x03 *(object-property)
null-type         = 0x05
undefined-type    = 0x06
ecma-array-type   = 0x08 array-count *(object-property)
strict-array-type = 0x0A array-count *(value-type)

value-typenumber-typestring-type など各記法の集合ですが、共通して 1 バイト目に識別用のマーカが存在しています。このマーカをもとに場合分けしてデータを読み取ります。

null-typeundefined-type はマーカ以外にデータを持ちません。 number-type はマーカの後ろに 8 バイトの倍精度浮動小数点数である DOUBLE をとります。 boolean-typeU8 をとり、 0x00 なら false 、 0x00 以外なら true となります。 string-typeUTF-8 ですので、文字列のバイト数 U16 と文字列部分 *(UTF8-char) がマーカの後に続きます。

次に複合型として

object-type       = 0x03 *(object-property)
ecma-array-type   = 0x08 array-count *(object-property)
strict-array-type = 0x0A array-count *(value-type)

object-property   = (UTF-8 value-type) | (UTF-8-empty 0x09)
array-count       = U32

ActionScript におけるオブジェクトおよび ECMAScript の配列は連想配列のように扱うことができます。これらのデータは object-type ないしは ecma-array-type として記述されます。 ecma-array-type の場合、 array-count = U32 で key-value ペアの数が記述されます。

AMF0 では、キーは数値であっても UTF-8 としてコードされます。そしてそれに対応する値は value-type で記述されます。 key-value ペア列挙の末端には 0x0000 0x09 (UTF-8-empty object-end-marker) が存在します。

一方で添字が数値の一般的な配列は strict-array-type の記法が用いられます。末端コードがないので、要素数array-count から取得する必要があります。

ともに値は value-type ですので、オブジェクトをネストすることも可能です。

仕様書

付随する説明や省略したデータ型などの情報は直接読んでください。10 ページちょっとの文書ですので。

ただし typo (というよりコピペミス?)と思われる箇所がいくつかみられます。

  • AMF0 仕様書
    • 5 ページ目
      • anonymous-object-type ではなく object-type
    • 6 ページ目 ecma-array-type の定義内
      • マーカがない
    • 7 ページ目 strict-array-type の定義内
      • マーカがない
    • 8 ページ目 object-type の定義内
      • object-type ではなく typed-object-type 。同様に typed-object-marker
    • ヘッダ
      • AMF 3 になってる

まあ typo じゃなくて正しい情報なのかもしれませんが、うーん。