📜 ⬆️ ⬇️

AS3 Vector in AMF3: we lift the curtain

Starting with the version of flash player 10.0, there is support for a new type of lists - vector. Vector is a typed, ordered list. More details can be found on the Adobe website . Tests show a good increase in read / write speed compared to simple arrays. (Not so long ago, soulburner published its tests ). Unfortunately, not a single PHP library (in other languages ​​other than AS3) supports this data type.

A little googling, an article was found that describes the deserialization of vectors in java. Everything turns out to be not so bad: there are four additional markers for Vector.<int> , Vector.<uint> , Vector.<Number> and Vector.<Object> . But I never managed to completely port the code - the server could not in any way deserialize the vector of objects (everything was in order with the numeric types). As a result, I had to put xdebug and start looking for myself “where the dog is buried”. As I suspected, the author of that article incorrectly implemented the parsing of a vector of objects and a little incorrect parsing of numerical vectors.

Vector specification

Adobe released the AMF3 protocol specification , but forgot (or did not want) to update it after the vectors appeared. Below you can see the addition of the specification for vectors.

 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))


As you can see, 4 additional markers were added: 3 special for numeric values ​​and one for the rest.
')
Comment. In fact, the specification is not entirely correct, namely the vector-other-type rule. According to the specification it turns out that such a vector can simultaneously contain all of the listed types, but in fact only one of the listed types. And only null-type can be used simultaneously with other types. Unfortunately, I do not know how to specify such a rule using ABNF.

Numeric Vectors

Everything is simple with them. Read the length of the vector, the fixed flag, and N values ​​( int , uint or double ). To be honest, I was surprised that these three vectors were rendered, especially against the background of the fact that the vectors of rows and boules are encoded as vectors of objects (more on this below).

Object Vector

Exactly the same as numerical vectors. The only difference is the additional parameter class-name , the name of the class whose objects contain a vector. class-name can be empty, meaning Object .

Vectors of strings, boules, arrays, vectors

I was unpleasantly surprised at how the vectors are encoded for the remaining “special types”. For them, a vector marker of objects with an empty string instead of a class-name . So without data it is impossible to know what exactly the vector contains, i.e. it is impossible to know what kind of vector arrived if it is empty.

Implementation

Because of these vectors for “special data types,” I also had difficulty in implementing vectors for PHP. The problem lies in the strict typing of vectors - a vector can store only one type of data. Here I was torn between 2 ways of implementation:
- simple but dumb container for arrays
- typesafe vector
With the first, everything is simple, but I want the second. As a result, the patch for Zend_Amf was never written, because I left the company for which I worked. And now there is no time to finish it. Therefore, I decided to simply lay out the specification. I am sure there are many who are willing to implement vector support in Zend_Amf, AMFPHP, WebORB, PyAMF, and others.

PS

The specification has not been thoroughly tested, so it may well not be complete. I would welcome any amendments.

Source: https://habr.com/ru/post/122178/


All Articles