Немного погуглив, была найдена статейка, в которой описывается десериализация векторов на java. Оказывается всё не так уж и плохо: существует четыре дополнительных маркера для
Vector.<int>, Vector.<uint>, Vector.<Number> и Vector.<Object>. Но у меня так и не получилось полностью портировать код — сервер никак не мог десериализовать вектор объектов (с числовым типами всё было в порядке). В итоге пришлось поставить xdebug и начать самому искать «где собака зарыта». Как я и подозревал, автор той статьи неправильно реализовал парсинг вектора объектов и немного некорректно парсинг числовых векторов.Спецификация векторов
Adobe выпустила спецификацию протокола AMF3, но забыла (или не захотела) обновить её после появления векторов. Ниже можно увидеть дополнение спецификации, касающееся векторов.
S32 = An signed 32-bit integer in big endian (network) byte order
vector-type = vector-int-type | vector-uint-type | vector-number-type |
vector-object-type | vector-other-type
value-type =| vector-type
vector-int-marker = 0x0D
vector-uint-marker = 0x0E
vector-number-marker = 0x0F
vector-object-marker = 0x10
U29V-len = U29 ; The first (low) bit is a flag with value 1.
; The remaining 1 to 28 significant bits are used to encode
; the length of the vector
vector-fixed-flag = U8
vector-int-type = vector-int-marker (U29O-ref | U29V-length vector-fixed-flag *(S32))
vector-uint-type = vector-uint-marker (U29O-ref | U29V-length vector-fixed-flag *(U32))
vector-number-type = vector-number-marker (U29O-ref | U29V-length vector-fixed-flag *(DOUBLE))
vector-object-type = vec tor-object-marker (U29O-ref | U29V-length vector-fixed-flag class-name
*(null-type | object-type))
vector-other-type = vector-object-marker (U29O-ref | U29V-length vector-fixed-flag UTF-8-empty
*(null-type | false-type | true-type | array-type | string-type |
vector-type | date-type | byte-array-type))
Как видно, было добавлено 4 дополнительных маркера: 3 специальных для числовых значений и один для всего остального.
Замечание. На самом деле спецификация не совсем верная, а именно
vector-other-type правило. По спецификации получается, что такой вектор может содержать одновременно все перечисленные типы, но на самом деле только один из перечисленных типов. И только null-type может использоваться одновременно с остальными типами. К сожалению я не знаю как указать такое правило с помощью ABNF.Числовые векторы
С ними всё просто. Читаем длину вектора,
fixed флаг, и N значений (int, uint или double). Если честно, меня удивило то, что эти три вектора были вынесены, особенно на фоне того что вектора строк и буленов кодируются как вектора объектов (об этом чуть ниже).Вектор объектов
Точно такой же как и числовые векторы. Единственное отличие — дополнительный параметр
class-name, имя класса, объекты которого содержит вектор. class-name может быть пустым, подразумевая под собой Object.Вектора строк, буленов, массивов, векторов
Я был неприятно удивлен тому, как кодируются векторы для остальных «спец-типов». Для них используется маркер вектора объектов с пустой строкой вместо
class-name. А значит без данных невозможно узнать, что именно содержит вектор, т.е. невозможно узнать, что за вектор приехал, если он пустой.Реализация
Из-за таких векторов для «особых типов данных» я и столкнулся с трудностями в реализации поддержки векторов для PHP. Проблема заключается именно в строгой типизации векторов — вектор может хранить только один тип данных. Тут меня разрывало между 2-мя способами реализации:
— простой, но тупой контейнер для массивов
— typesafe вектора
С первым всё просто, но хочется второго. В итоге патч для Zend_Amf так и не был написан, потому что я покинул компанию, на которую работал. А сейчас нет времени закончить его. Поэтому решил просто выложить спецификацию. Я уверен найдётся много желающих, готовых реализовать поддержку векторов в Zend_Amf, AMFPHP, WebORB, PyAMF и остальных.
P.S.
Спецификация не проходила тщательного тестирования, поэтому она вполне может быть не полной. Буду рад любым поправкам.

