Начиная с версии flash player 10.0, появилась поддержка нового вида списков — vector. Vector — это типизированный, упорядоченный список. Более подробно можно почитать на сайте Adobe. Тесты показывают неплохой прирост по скорости чтения/записи по сравнению с простыми массивами. (Не так давно soulburner опубликовал свои тесты). К несчастью, ни одна библиотека на PHP (да в прочем и на других языках, не считая AS3) не поддерживает этот тип данных.
Немного погуглив, была найдена статейка, в которой описывается десериализация векторов на java. Оказывается всё не так уж и плохо: существует четыре дополнительных маркера для
Adobe выпустила спецификацию протокола AMF3, но забыла (или не захотела) обновить её после появления векторов. Ниже можно увидеть дополнение спецификации, касающееся векторов.
Как видно, было добавлено 4 дополнительных маркера: 3 специальных для числовых значений и один для всего остального.
Замечание. На самом деле спецификация не совсем верная, а именно
С ними всё просто. Читаем длину вектора,
Точно такой же как и числовые векторы. Единственное отличие — дополнительный параметр
Я был неприятно удивлен тому, как кодируются векторы для остальных «спец-типов». Для них используется маркер вектора объектов с пустой строкой вместо
Из-за таких векторов для «особых типов данных» я и столкнулся с трудностями в реализации поддержки векторов для PHP. Проблема заключается именно в строгой типизации векторов — вектор может хранить только один тип данных. Тут меня разрывало между 2-мя способами реализации:
— простой, но тупой контейнер для массивов
— typesafe вектора
С первым всё просто, но хочется второго. В итоге патч для Zend_Amf так и не был написан, потому что я покинул компанию, на которую работал. А сейчас нет времени закончить его. Поэтому решил просто выложить спецификацию. Я уверен найдётся много желающих, готовых реализовать поддержку векторов в Zend_Amf, AMFPHP, WebORB, PyAMF и остальных.
Спецификация не проходила тщательного тестирования, поэтому она вполне может быть не полной. Буду рад любым поправкам.
Немного погуглив, была найдена статейка, в которой описывается десериализация векторов на 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.
Спецификация не проходила тщательного тестирования, поэтому она вполне может быть не полной. Буду рад любым поправкам.