<s> from . compat import OrderedDict , is_py2 , str , bytes , integer_types , string_types <EOL> from . util import pack_bytes_into <EOL> from collections import namedtuple <EOL> from struct import Struct , error as struct_error <EOL> from inspect import getargspec <EOL> ( SCRIPT_DATA_TYPE_NUMBER , SCRIPT_DATA_TYPE_BOOLEAN , <EOL> SCRIPT_DATA_TYPE_STRING , SCRIPT_DATA_TYPE_OBJECT , <EOL> SCRIPT_DATA_TYPE_RESERVED , SCRIPT_DATA_TYPE_NULL , <EOL> SCRIPT_DATA_TYPE_UNDEFINED , SCRIPT_DATA_TYPE_REFERENCE , <EOL> SCRIPT_DATA_TYPE_ECMAARRAY , SCRIPT_DATA_TYPE_OBJECTEND , <EOL> SCRIPT_DATA_TYPE_STRICTARRAY , SCRIPT_DATA_TYPE_DATE , <EOL> SCRIPT_DATA_TYPE_LONGSTRING ) = range ( <NUM_LIT> ) <EOL> SCRIPT_DATA_TYPE_AMF3 = <NUM_LIT> <EOL> ( AMF3_TYPE_UNDEFINED , AMF3_TYPE_NULL , AMF3_TYPE_FALSE , AMF3_TYPE_TRUE , <EOL> AMF3_TYPE_INTEGER , AMF3_TYPE_DOUBLE , AMF3_TYPE_STRING , AMF3_TYPE_XML_DOC , <EOL> AMF3_TYPE_DATE , AMF3_TYPE_ARRAY , AMF3_TYPE_OBJECT , AMF3_TYPE_XML , <EOL> AMF3_TYPE_BYTE_ARRAY , AMF3_TYPE_VECTOR_INT , AMF3_TYPE_VECTOR_UINT , <EOL> AMF3_TYPE_VECTOR_DOUBLE , AMF3_TYPE_VECTOR_OBJECT , AMF3_TYPE_DICT ) = range ( <NUM_LIT> ) <EOL> AMF3_EMPTY_STRING = <NUM_LIT> <EOL> AMF3_DYNAMIC_OBJECT = <NUM_LIT> <EOL> AMF3_CLOSE_DYNAMIC_OBJECT = <NUM_LIT> <EOL> AMF3_CLOSE_DYNAMIC_ARRAY = <NUM_LIT> <EOL> AMF3_MIN_INTEGER = - <NUM_LIT> <EOL> AMF3_MAX_INTEGER = <NUM_LIT> <EOL> class PrimitiveType ( Struct ) : <EOL> def __call__ ( self , * args ) : <EOL> return self . pack ( * args ) <EOL> def read ( self , fd ) : <EOL> data = fd . read ( self . size ) <EOL> if len ( data ) != self . size : <EOL> raise IOError ( "<STR_LIT>" ) <EOL> return self . unpack ( data ) [ <NUM_LIT:0> ] <EOL> class PrimitiveClassType ( PrimitiveType ) : <EOL> def __init__ ( self , format , cls ) : <EOL> self . cls = cls <EOL> PrimitiveType . __init__ ( self , format ) <EOL> def pack ( self , val ) : <EOL> return PrimitiveType . pack ( self , * val ) <EOL> def pack_into ( self , buf , offset , val ) : <EOL> return PrimitiveType . pack_into ( self , buf , offset , * val ) <EOL> def unpack ( self , data ) : <EOL> vals = PrimitiveType . unpack ( self , data ) <EOL> rval = self . cls ( * vals ) <EOL> return ( rval , ) <EOL> def unpack_from ( self , buf , offset ) : <EOL> vals = PrimitiveType . unpack_from ( self , buf , offset ) <EOL> rval = self . cls ( * vals ) <EOL> return ( rval , ) <EOL> class DynamicType ( object ) : <EOL> def __new__ ( cls , * args , ** kwargs ) : <EOL> return cls . pack ( * args , ** kwargs ) <EOL> @ classmethod <EOL> def size ( cls , val ) : <EOL> raise NotImplementedError <EOL> @ classmethod <EOL> def pack ( cls , val ) : <EOL> raise NotImplementedError <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , val ) : <EOL> raise NotImplementedError <EOL> @ classmethod <EOL> def read ( cls , fd ) : <EOL> raise NotImplementedError <EOL> @ classmethod <EOL> def unpack_from ( cls , buf , offset ) : <EOL> raise NotImplementedError <EOL> @ classmethod <EOL> def unpack ( cls , buf ) : <EOL> return cls . unpack_from ( buf , <NUM_LIT:0> ) <EOL> class TwosComplement ( PrimitiveType ) : <EOL> def __init__ ( self , primitive ) : <EOL> self . primitive = primitive <EOL> bits = self . primitive . size * <NUM_LIT:8> <EOL> self . maxval = <NUM_LIT:1> << bits <EOL> self . midval = self . maxval >> <NUM_LIT:1> <EOL> self . upper = self . midval - <NUM_LIT:1> <EOL> self . lower = - self . midval <EOL> @ property <EOL> def size ( self ) : <EOL> return <NUM_LIT:3> <EOL> def pack ( self , val ) : <EOL> if val < self . lower or val > self . upper : <EOL> msg = "<STR_LIT>" . format ( self . primitive . format , <EOL> self . lower , self . upper ) <EOL> raise struct_error ( msg ) <EOL> if val < <NUM_LIT:0> : <EOL> val = val + self . maxval <EOL> return self . primitive . pack ( val ) <EOL> def pack_into ( self , buf , offset , val ) : <EOL> if val < self . lower or val > self . upper : <EOL> msg = "<STR_LIT>" . format ( self . primitive . format , <EOL> self . lower , self . upper ) <EOL> raise struct_error ( msg ) <EOL> if val < <NUM_LIT:0> : <EOL> val = val + self . maxval <EOL> return self . primitive . pack_into ( buf , offset , val ) <EOL> def unpack ( self , data ) : <EOL> val = self . primitive . unpack ( data ) [ <NUM_LIT:0> ] <EOL> if val & self . midval : <EOL> val = val - self . maxval <EOL> return ( val , ) <EOL> def unpack_from ( self , buf , offset ) : <EOL> val = self . primitive . unpack_from ( buf , offset ) [ <NUM_LIT:0> ] <EOL> if val & self . midval : <EOL> val = val - self . maxval <EOL> return ( val , ) <EOL> class HighLowCombo ( PrimitiveType ) : <EOL> def __init__ ( self , format , highbits , reverse = True ) : <EOL> PrimitiveType . __init__ ( self , format ) <EOL> self . highbits = highbits <EOL> self . lowmask = ( <NUM_LIT:1> << highbits ) - <NUM_LIT:1> <EOL> self . reverse = reverse <EOL> self . lower = <NUM_LIT:0> <EOL> self . upper = ( <NUM_LIT:1> << ( self . size * <NUM_LIT:8> ) ) - <NUM_LIT:1> <EOL> def pack ( self , val ) : <EOL> if val < self . lower or val > self . upper : <EOL> msg = "<STR_LIT>" . format ( self . format , <EOL> self . lower , self . upper ) <EOL> raise struct_error ( msg ) <EOL> if self . reverse : <EOL> high = val >> self . highbits <EOL> low = val & self . lowmask <EOL> else : <EOL> high = val & self . lowmask <EOL> low = val >> self . highbits <EOL> return PrimitiveType . pack ( self , high , low ) <EOL> def pack_into ( self , buf , offset , val ) : <EOL> if val < self . lower or val > self . upper : <EOL> msg = "<STR_LIT>" . format ( self . format , <EOL> self . lower , self . upper ) <EOL> raise struct_error ( msg ) <EOL> if self . reverse : <EOL> high = val >> self . highbits <EOL> low = val & self . lowmask <EOL> else : <EOL> high = val & self . lowmask <EOL> low = val >> self . highbits <EOL> return PrimitiveType . pack_into ( self , buf , offset , high , low ) <EOL> def unpack ( self , data ) : <EOL> high , low = PrimitiveType . unpack ( self , data ) <EOL> if self . reverse : <EOL> ret = high << self . highbits <EOL> ret |= low <EOL> else : <EOL> ret = high <EOL> ret |= low << self . highbits <EOL> return ( ret , ) <EOL> def unpack_from ( self , buf , offset ) : <EOL> high , low = PrimitiveType . unpack_from ( self , buf , offset ) <EOL> if self . reverse : <EOL> ret = high << self . highbits <EOL> ret |= low <EOL> else : <EOL> ret = high <EOL> ret |= low << self . highbits <EOL> return ( ret , ) <EOL> class FixedPoint ( PrimitiveType ) : <EOL> def __init__ ( self , format , bits ) : <EOL> self . divider = float ( <NUM_LIT:1> << bits ) <EOL> PrimitiveType . __init__ ( self , format ) <EOL> def pack ( self , val ) : <EOL> val *= self . divider <EOL> return PrimitiveType . pack ( self , int ( val ) ) <EOL> def pack_into ( self , buf , offset , val ) : <EOL> val *= self . divider <EOL> return PrimitiveType . pack_into ( self , buf , offset , int ( val ) ) <EOL> def unpack ( self , data ) : <EOL> val = PrimitiveType . unpack ( self , data ) [ <NUM_LIT:0> ] <EOL> val /= self . divider <EOL> return ( val , ) <EOL> def unpack_from ( self , buf , offset ) : <EOL> val = PrimitiveType . unpack_from ( self , buf , offset ) [ <NUM_LIT:0> ] <EOL> val /= self . divider <EOL> return ( val , ) <EOL> class PaddedBytes ( PrimitiveType ) : <EOL> def __init__ ( self , size , padding ) : <EOL> self . padded_size = size <EOL> self . padding = bytes ( padding , "<STR_LIT:ascii>" ) <EOL> @ property <EOL> def size ( self ) : <EOL> return self . padded_size <EOL> def pack ( self , val ) : <EOL> rval = bytes ( val [ : self . size ] , "<STR_LIT:ascii>" ) <EOL> if len ( rval ) < self . size : <EOL> paddinglen = self . size - len ( rval ) <EOL> rval += self . padding * paddinglen <EOL> return rval <EOL> def pack_into ( self , buf , offset , val ) : <EOL> rval = bytes ( val [ : self . size ] , "<STR_LIT:ascii>" ) <EOL> offset = pack_bytes_into ( buf , offset , rval ) <EOL> if len ( rval ) < self . size : <EOL> paddinglen = self . size - len ( rval ) <EOL> offset = pack_bytes_into ( buf , offset , self . padding * paddinglen ) <EOL> def unpack ( self , data ) : <EOL> return ( str ( data . rstrip ( self . padding ) , "<STR_LIT:ascii>" ) , ) <EOL> def unpack_from ( self , buf , offset ) : <EOL> data = buf [ offset : offset + self . padded_size ] <EOL> return ( str ( data . rstrip ( self . padding ) , "<STR_LIT:ascii>" ) , ) <EOL> """<STR_LIT>""" <EOL> U8 = PrimitiveType ( "<STR_LIT:B>" ) <EOL> S8 = PrimitiveType ( "<STR_LIT:b>" ) <EOL> """<STR_LIT>""" <EOL> U16BE = PrimitiveType ( "<STR_LIT>" ) <EOL> S16BE = PrimitiveType ( "<STR_LIT>" ) <EOL> U16LE = PrimitiveType ( "<STR_LIT>" ) <EOL> S16LE = PrimitiveType ( "<STR_LIT>" ) <EOL> """<STR_LIT>""" <EOL> U24BE = HighLowCombo ( "<STR_LIT>" , <NUM_LIT:8> , True ) <EOL> S24BE = TwosComplement ( U24BE ) <EOL> U24LE = HighLowCombo ( "<STR_LIT>" , <NUM_LIT:16> , False ) <EOL> S24LE = TwosComplement ( U24LE ) <EOL> """<STR_LIT>""" <EOL> U32BE = PrimitiveType ( "<STR_LIT>" ) <EOL> S32BE = PrimitiveType ( "<STR_LIT>" ) <EOL> U32LE = PrimitiveType ( "<STR_LIT>" ) <EOL> S32LE = PrimitiveType ( "<STR_LIT>" ) <EOL> """<STR_LIT>""" <EOL> U64BE = PrimitiveType ( "<STR_LIT>" ) <EOL> U64LE = PrimitiveType ( "<STR_LIT>" ) <EOL> """<STR_LIT>""" <EOL> U8_8BE = FixedPoint ( "<STR_LIT>" , <NUM_LIT:8> ) <EOL> S8_8BE = FixedPoint ( "<STR_LIT>" , <NUM_LIT:8> ) <EOL> U16_16BE = FixedPoint ( "<STR_LIT>" , <NUM_LIT:16> ) <EOL> S16_16BE = FixedPoint ( "<STR_LIT>" , <NUM_LIT:16> ) <EOL> U8_8LE = FixedPoint ( "<STR_LIT>" , <NUM_LIT:8> ) <EOL> S8_8LE = FixedPoint ( "<STR_LIT>" , <NUM_LIT:8> ) <EOL> U16_16LE = FixedPoint ( "<STR_LIT>" , <NUM_LIT:16> ) <EOL> S16_16LE = FixedPoint ( "<STR_LIT>" , <NUM_LIT:16> ) <EOL> DoubleLE = PrimitiveType ( "<STR_LIT>" ) <EOL> DoubleBE = PrimitiveType ( "<STR_LIT>" ) <EOL> """<STR_LIT>""" <EOL> FourCC = PaddedBytes ( <NUM_LIT:4> , "<STR_LIT:U+0020>" ) <EOL> """<STR_LIT>""" <EOL> ScriptDataNumber = DoubleBE <EOL> ScriptDataBoolean = PrimitiveType ( "<STR_LIT:?>" ) <EOL> class U3264 ( DynamicType ) : <EOL> @ classmethod <EOL> def size ( cls , val , version ) : <EOL> if version == <NUM_LIT:1> : <EOL> return U64BE . size <EOL> else : <EOL> return U32BE . size <EOL> @ classmethod <EOL> def pack ( cls , val , version ) : <EOL> if version == <NUM_LIT:1> : <EOL> return U64BE ( val ) <EOL> else : <EOL> return U32BE ( val ) <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , val , version ) : <EOL> if version == <NUM_LIT:1> : <EOL> prim = U64BE <EOL> else : <EOL> prim = U32BE <EOL> prim . pack_into ( buf , offset , val ) <EOL> return offset + prim . size <EOL> @ classmethod <EOL> def read ( cls , fd , version ) : <EOL> if version == <NUM_LIT:1> : <EOL> return U64BE . read ( fd ) <EOL> else : <EOL> return U32BE . read ( fd ) <EOL> @ classmethod <EOL> def unpack_from ( cls , buf , offset , version ) : <EOL> if version == <NUM_LIT:1> : <EOL> prim = U64BE <EOL> else : <EOL> prim = U32BE <EOL> rval = prim . unpack_from ( buf , offset ) <EOL> offset += prim . size <EOL> return ( rval , offset ) <EOL> class String ( DynamicType ) : <EOL> @ classmethod <EOL> def size ( cls , * args , ** kwargs ) : <EOL> return len ( cls . pack ( * args , ** kwargs ) ) <EOL> @ classmethod <EOL> def pack ( cls , val , encoding = "<STR_LIT:utf8>" , errors = "<STR_LIT:ignore>" ) : <EOL> rval = val . encode ( encoding , errors ) <EOL> return rval <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , val , <EOL> encoding = "<STR_LIT:utf8>" , errors = "<STR_LIT:ignore>" ) : <EOL> return pack_bytes_into ( buf , offset , <EOL> val . encode ( encoding , errors ) ) <EOL> class CString ( String ) : <EOL> EndMarker = b"<STR_LIT:\x00>" <EOL> @ classmethod <EOL> def pack ( cls , * args , ** kwargs ) : <EOL> rval = String . pack ( * args , ** kwargs ) <EOL> rval += CString . EndMarker <EOL> return rval <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , * args , ** kwargs ) : <EOL> offset = String . pack_into ( buf , offset , * args , ** kwargs ) <EOL> U8 . pack_into ( buf , offset , <NUM_LIT:0> ) <EOL> return offset + <NUM_LIT:1> <EOL> @ classmethod <EOL> def read ( cls , fd , encoding = "<STR_LIT:utf8>" , errors = "<STR_LIT:ignore>" ) : <EOL> rval = b"<STR_LIT>" <EOL> while True : <EOL> ch = fd . read ( <NUM_LIT:1> ) <EOL> if len ( ch ) == <NUM_LIT:0> or ch == CString . EndMarker : <EOL> break <EOL> rval += ch <EOL> return rval . decode ( encoding , errors ) <EOL> @ classmethod <EOL> def unpack_from ( cls , buf , offset , encoding = "<STR_LIT:utf8>" , errors = "<STR_LIT:ignore>" ) : <EOL> end = buf [ offset : ] . find ( b"<STR_LIT:\x00>" ) <EOL> rval = buf [ offset : offset + end ] . decode ( encoding , errors ) <EOL> offset += end + <NUM_LIT:1> <EOL> return ( rval , offset ) <EOL> class ScriptDataType ( object ) : <EOL> __identifier__ = <NUM_LIT:0> <EOL> class ScriptDataString ( String ) : <EOL> __size_primitive__ = U16BE <EOL> @ classmethod <EOL> def pack ( cls , val , * args , ** kwargs ) : <EOL> rval = String . pack ( val , * args , ** kwargs ) <EOL> size = cls . __size_primitive__ ( len ( rval ) ) <EOL> return size + rval <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , val , * args , ** kwargs ) : <EOL> noffset = String . pack_into ( buf , offset + cls . __size_primitive__ . size , <EOL> val , * args , ** kwargs ) <EOL> cls . __size_primitive__ . pack_into ( buf , offset , <EOL> ( noffset - offset ) - cls . __size_primitive__ . size ) <EOL> return noffset <EOL> @ classmethod <EOL> def read ( cls , fd , encoding = "<STR_LIT:utf8>" , errors = "<STR_LIT:ignore>" ) : <EOL> size = cls . __size_primitive__ . read ( fd ) <EOL> data = fd . read ( size ) <EOL> return data . decode ( encoding , errors ) <EOL> @ classmethod <EOL> def unpack_from ( cls , buf , offset , encoding = "<STR_LIT:utf8>" , errors = "<STR_LIT:ignore>" ) : <EOL> size = cls . __size_primitive__ . unpack_from ( buf , offset ) [ <NUM_LIT:0> ] <EOL> offset += cls . __size_primitive__ . size <EOL> data = buf [ offset : offset + size ] . decode ( encoding , errors ) <EOL> offset += size <EOL> return ( data , offset ) <EOL> class ScriptDataLongString ( ScriptDataString ) : <EOL> __size_primitive__ = U32BE <EOL> class ScriptDataObjectEnd ( Exception ) : <EOL> pass <EOL> class ScriptDataObject ( OrderedDict , ScriptDataType ) : <EOL> __identifier__ = SCRIPT_DATA_TYPE_OBJECT <EOL> @ classmethod <EOL> def size ( cls , val ) : <EOL> size = <NUM_LIT:3> <EOL> for key , value in val . items ( ) : <EOL> size += ScriptDataString . size ( key ) <EOL> size += ScriptDataValue . size ( value ) <EOL> return size <EOL> @ classmethod <EOL> def pack ( cls , val ) : <EOL> rval = b"<STR_LIT>" <EOL> for key , value in val . items ( ) : <EOL> rval += ScriptDataString ( key ) <EOL> rval += ScriptDataValue . pack ( value ) <EOL> rval += ScriptDataString ( "<STR_LIT>" ) <EOL> rval += U8 ( SCRIPT_DATA_TYPE_OBJECTEND ) <EOL> return rval <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , val ) : <EOL> for key , value in val . items ( ) : <EOL> offset = ScriptDataString . pack_into ( buf , offset , key ) <EOL> offset = ScriptDataValue . pack_into ( buf , offset , value ) <EOL> offset = ScriptDataString . pack_into ( buf , offset , "<STR_LIT>" ) <EOL> U8 . pack_into ( buf , offset , SCRIPT_DATA_TYPE_OBJECTEND ) <EOL> return offset + U8 . size <EOL> @ classmethod <EOL> def read ( cls , fd ) : <EOL> rval = cls ( ) <EOL> while True : <EOL> try : <EOL> key = ScriptDataString . read ( fd ) <EOL> value = ScriptDataValue . read ( fd ) <EOL> except ScriptDataObjectEnd : <EOL> break <EOL> if len ( key ) == <NUM_LIT:0> : <EOL> break <EOL> rval [ key ] = value <EOL> return rval <EOL> @ classmethod <EOL> def unpack_from ( cls , buf , offset ) : <EOL> rval = cls ( ) <EOL> while True : <EOL> try : <EOL> key , offset = ScriptDataString . unpack_from ( buf , offset ) <EOL> value , offset = ScriptDataValue . unpack_from ( buf , offset ) <EOL> except ScriptDataObjectEnd : <EOL> offset += <NUM_LIT:1> <EOL> break <EOL> if len ( key ) == <NUM_LIT:0> : <EOL> break <EOL> rval [ key ] = value <EOL> return ( rval , offset ) <EOL> class ScriptDataECMAArray ( ScriptDataObject ) : <EOL> __identifier__ = SCRIPT_DATA_TYPE_ECMAARRAY <EOL> @ classmethod <EOL> def size ( cls , val ) : <EOL> return <NUM_LIT:4> + ScriptDataObject . size ( val ) <EOL> @ classmethod <EOL> def pack ( cls , val ) : <EOL> rval = U32BE ( len ( val ) ) <EOL> rval += ScriptDataObject . pack ( val ) <EOL> return rval <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , val ) : <EOL> U32BE . pack_into ( buf , offset , len ( val ) ) <EOL> return ScriptDataObject . pack_into ( buf , offset + U32BE . size , <EOL> val ) <EOL> @ classmethod <EOL> def read ( cls , fd ) : <EOL> U32BE . read ( fd ) <EOL> val = ScriptDataObject . read ( fd ) <EOL> return cls ( val ) <EOL> @ classmethod <EOL> def unpack_from ( cls , buf , offset ) : <EOL> U32BE . unpack_from ( buf , offset ) <EOL> offset += U32BE . size <EOL> val , offset = ScriptDataObject . unpack_from ( buf , offset ) <EOL> return ( cls ( val ) , offset ) <EOL> class ScriptDataStrictArray ( DynamicType ) : <EOL> @ classmethod <EOL> def size ( cls , val ) : <EOL> size = <NUM_LIT:4> <EOL> for sdval in val : <EOL> size += ScriptDataValue . size ( sdval ) <EOL> return size <EOL> @ classmethod <EOL> def pack ( cls , val ) : <EOL> rval = U32BE ( len ( val ) ) <EOL> for sdval in val : <EOL> rval += ScriptDataValue . pack ( sdval ) <EOL> return rval <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , val ) : <EOL> U32BE . pack_into ( buf , offset , len ( val ) ) <EOL> offset += U32BE . size <EOL> for sdval in val : <EOL> offset = ScriptDataValue . pack_into ( buf , offset , sdval ) <EOL> return offset <EOL> @ classmethod <EOL> def read ( cls , fd ) : <EOL> length = U32BE . read ( fd ) <EOL> rval = [ ] <EOL> for i in range ( length ) : <EOL> val = ScriptDataValue . read ( fd ) <EOL> rval . append ( val ) <EOL> return rval <EOL> @ classmethod <EOL> def unpack_from ( cls , buf , offset ) : <EOL> length = U32BE . unpack_from ( buf , offset ) [ <NUM_LIT:0> ] <EOL> offset += U32BE . size <EOL> rval = [ ] <EOL> for i in range ( length ) : <EOL> val , offset = ScriptDataValue . unpack_from ( buf , offset ) <EOL> rval . append ( val ) <EOL> return ( rval , offset ) <EOL> ScriptDataDate = namedtuple ( "<STR_LIT>" , [ "<STR_LIT>" , "<STR_LIT>" ] ) <EOL> ScriptDataDateStruct = PrimitiveClassType ( "<STR_LIT>" , ScriptDataDate ) <EOL> ScriptDataDate . __identifier__ = SCRIPT_DATA_TYPE_DATE <EOL> ScriptDataDate . __packer__ = ScriptDataDateStruct <EOL> ScriptDataReference = namedtuple ( "<STR_LIT>" , [ "<STR_LIT>" ] ) <EOL> ScriptDataReferenceStruct = PrimitiveClassType ( "<STR_LIT>" , ScriptDataReference ) <EOL> ScriptDataReference . __identifier__ = SCRIPT_DATA_TYPE_REFERENCE <EOL> ScriptDataReference . __packer__ = ScriptDataReferenceStruct <EOL> class ScriptDataValue ( DynamicType , ScriptDataType ) : <EOL> PrimitiveReaders = { <EOL> SCRIPT_DATA_TYPE_NUMBER : ScriptDataNumber , <EOL> SCRIPT_DATA_TYPE_BOOLEAN : ScriptDataBoolean , <EOL> SCRIPT_DATA_TYPE_REFERENCE : ScriptDataReferenceStruct , <EOL> SCRIPT_DATA_TYPE_DATE : ScriptDataDateStruct , <EOL> } <EOL> DynamicReaders = { <EOL> SCRIPT_DATA_TYPE_STRING : ScriptDataString , <EOL> SCRIPT_DATA_TYPE_LONGSTRING : ScriptDataLongString , <EOL> SCRIPT_DATA_TYPE_OBJECT : ScriptDataObject , <EOL> SCRIPT_DATA_TYPE_ECMAARRAY : ScriptDataECMAArray , <EOL> SCRIPT_DATA_TYPE_STRICTARRAY : ScriptDataStrictArray , <EOL> } <EOL> Readers = PrimitiveReaders . copy ( ) <EOL> Readers . update ( DynamicReaders ) <EOL> @ classmethod <EOL> def size ( cls , val ) : <EOL> size = <NUM_LIT:1> <EOL> if isinstance ( val , bool ) : <EOL> size += ScriptDataBoolean . size <EOL> elif isinstance ( val , ( int , float ) ) : <EOL> size += ScriptDataNumber . size <EOL> elif isinstance ( val , list ) : <EOL> size += ScriptDataStrictArray . size ( val ) <EOL> elif isinstance ( val , string_types ) : <EOL> if len ( val ) > <NUM_LIT> : <EOL> size += ScriptDataLongString . size ( val ) <EOL> else : <EOL> size += ScriptDataString . size ( val ) <EOL> elif isinstance ( val , ScriptDataType ) : <EOL> cls = type ( val ) <EOL> size += cls . size ( val ) <EOL> elif type ( val ) in ( ScriptDataDate , ScriptDataReference ) : <EOL> cls = type ( val ) <EOL> packer = cls . __packer__ <EOL> size += packer . size <EOL> elif isinstance ( val , AMF3ObjectBase ) : <EOL> size += U8 . size <EOL> size += AMF3Value . size ( val ) <EOL> return size <EOL> @ classmethod <EOL> def pack ( cls , val ) : <EOL> rval = b"<STR_LIT>" <EOL> if isinstance ( val , bool ) : <EOL> rval += U8 ( SCRIPT_DATA_TYPE_BOOLEAN ) <EOL> rval += ScriptDataBoolean ( val ) <EOL> elif isinstance ( val , ( int , float ) ) : <EOL> rval += U8 ( SCRIPT_DATA_TYPE_NUMBER ) <EOL> rval += ScriptDataNumber ( val ) <EOL> elif isinstance ( val , list ) : <EOL> rval += U8 ( SCRIPT_DATA_TYPE_STRICTARRAY ) <EOL> rval += ScriptDataStrictArray ( val ) <EOL> elif isinstance ( val , string_types ) : <EOL> if len ( val ) > <NUM_LIT> : <EOL> rval += U8 ( SCRIPT_DATA_TYPE_LONGSTRING ) <EOL> rval += ScriptDataLongString ( val ) <EOL> else : <EOL> rval += U8 ( SCRIPT_DATA_TYPE_STRING ) <EOL> rval += ScriptDataString ( val ) <EOL> elif val is None : <EOL> rval += U8 ( SCRIPT_DATA_TYPE_NULL ) <EOL> elif isinstance ( val , ScriptDataType ) : <EOL> cls = type ( val ) <EOL> rval += U8 ( cls . __identifier__ ) <EOL> rval += cls . pack ( val ) <EOL> elif type ( val ) in ( ScriptDataDate , ScriptDataReference ) : <EOL> cls = type ( val ) <EOL> packer = cls . __packer__ <EOL> rval += U8 ( cls . __identifier__ ) <EOL> rval += packer . pack ( val ) <EOL> elif isinstance ( val , AMF3ObjectBase ) : <EOL> rval += U8 ( SCRIPT_DATA_TYPE_AMF3 ) <EOL> rval += AMF3Value . pack ( val ) <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" . format ( type ( val ) ) ) <EOL> return rval <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , val ) : <EOL> if isinstance ( val , bool ) : <EOL> U8 . pack_into ( buf , offset , SCRIPT_DATA_TYPE_BOOLEAN ) <EOL> offset += U8 . size <EOL> ScriptDataBoolean . pack_into ( buf , offset , val ) <EOL> offset += ScriptDataBoolean . size <EOL> elif isinstance ( val , ( int , float ) ) : <EOL> U8 . pack_into ( buf , offset , SCRIPT_DATA_TYPE_NUMBER ) <EOL> offset += U8 . size <EOL> ScriptDataNumber . pack_into ( buf , offset , val ) <EOL> offset += ScriptDataNumber . size <EOL> elif isinstance ( val , list ) : <EOL> U8 . pack_into ( buf , offset , SCRIPT_DATA_TYPE_STRICTARRAY ) <EOL> offset += U8 . size <EOL> offset = ScriptDataStrictArray . pack_into ( buf , offset , val ) <EOL> elif isinstance ( val , string_types ) : <EOL> if len ( val ) > <NUM_LIT> : <EOL> U8 . pack_into ( buf , offset , SCRIPT_DATA_TYPE_LONGSTRING ) <EOL> offset += U8 . size <EOL> offset = ScriptDataLongString . pack_into ( buf , offset , val ) <EOL> else : <EOL> U8 . pack_into ( buf , offset , SCRIPT_DATA_TYPE_STRING ) <EOL> offset += U8 . size <EOL> offset = ScriptDataString . pack_into ( buf , offset , val ) <EOL> elif val is None : <EOL> U8 . pack_into ( buf , offset , SCRIPT_DATA_TYPE_NULL ) <EOL> elif isinstance ( val , ScriptDataType ) : <EOL> cls = type ( val ) <EOL> U8 . pack_into ( buf , offset , cls . __identifier__ ) <EOL> offset += U8 . size <EOL> offset = cls . pack_into ( buf , offset , val ) <EOL> elif type ( val ) in ( ScriptDataDate , ScriptDataReference ) : <EOL> cls = type ( val ) <EOL> packer = cls . __packer__ <EOL> U8 . pack_into ( buf , offset , cls . __identifier__ ) <EOL> offset += U8 . size <EOL> packer . pack_into ( buf , offset , val ) <EOL> offset += packer . size <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" . format ( type ( val ) ) ) <EOL> return offset <EOL> @ classmethod <EOL> def read ( cls , fd , marker = None ) : <EOL> if marker is None : <EOL> type_ = U8 . read ( fd ) <EOL> else : <EOL> type_ = marker <EOL> if type_ == SCRIPT_DATA_TYPE_AMF3 : <EOL> return AMF3Value . read ( fd ) <EOL> elif type_ in ScriptDataValue . Readers : <EOL> return ScriptDataValue . Readers [ type_ ] . read ( fd ) <EOL> elif type_ == SCRIPT_DATA_TYPE_OBJECTEND : <EOL> raise ScriptDataObjectEnd <EOL> elif ( type_ == SCRIPT_DATA_TYPE_NULL or <EOL> type_ == SCRIPT_DATA_TYPE_UNDEFINED ) : <EOL> return None <EOL> else : <EOL> raise IOError ( "<STR_LIT>" . format ( type_ ) ) <EOL> @ classmethod <EOL> def unpack_from ( cls , buf , offset ) : <EOL> type_ = U8 . unpack_from ( buf , offset ) [ <NUM_LIT:0> ] <EOL> offset += U8 . size <EOL> if type_ in ScriptDataValue . DynamicReaders : <EOL> return ScriptDataValue . Readers [ type_ ] . unpack_from ( buf , offset ) <EOL> elif type_ in ScriptDataValue . PrimitiveReaders : <EOL> reader = ScriptDataValue . PrimitiveReaders [ type_ ] <EOL> rval = reader . unpack_from ( buf , offset ) [ <NUM_LIT:0> ] <EOL> offset += reader . size <EOL> return ( rval , offset ) <EOL> elif type_ == SCRIPT_DATA_TYPE_OBJECTEND : <EOL> raise ScriptDataObjectEnd <EOL> elif ( type_ == SCRIPT_DATA_TYPE_NULL or <EOL> type_ == SCRIPT_DATA_TYPE_UNDEFINED ) : <EOL> return ( None , offset ) <EOL> else : <EOL> raise IOError ( "<STR_LIT>" . format ( hex ( type_ ) ) ) <EOL> class AMF0Value ( ScriptDataValue ) : <EOL> pass <EOL> class AMF0String ( ScriptDataString ) : <EOL> pass <EOL> AMF0Number = ScriptDataNumber <EOL> AMF3Double = ScriptDataNumber <EOL> class AMF3Type ( ScriptDataType ) : <EOL> pass <EOL> class AMF3Integer ( DynamicType , AMF3Type ) : <EOL> __identifier__ = AMF3_TYPE_INTEGER <EOL> @ classmethod <EOL> def size ( cls , val ) : <EOL> val &= <NUM_LIT> <EOL> if val < <NUM_LIT> : <EOL> return <NUM_LIT:1> <EOL> elif val < <NUM_LIT> : <EOL> return <NUM_LIT:2> <EOL> elif val < <NUM_LIT> : <EOL> return <NUM_LIT:3> <EOL> elif val < <NUM_LIT> : <EOL> return <NUM_LIT:4> <EOL> @ classmethod <EOL> def pack ( cls , val ) : <EOL> size = cls . size ( val ) <EOL> buf = bytearray ( size ) <EOL> offset = cls . pack_into ( buf , <NUM_LIT:0> , val ) <EOL> return bytes ( buf [ : offset ] ) <EOL> @ classmethod <EOL> def pack_into ( cls , buf , offset , val ) : <EOL> val &= <NUM_LIT> <EOL> if val < <NUM_LIT> : <EOL> buf [ offset ] = val <EOL> offset += <NUM_LIT:1> <EOL> elif val < <NUM_LIT> : <EOL> buf [ offset ] = ( val >> <NUM_LIT:7> & <NUM_LIT> ) | <NUM_LIT> <EOL> buf [ offset + <NUM_LIT:1> ] = val & <NUM_LIT> <EOL> offset += <NUM_LIT:2> <EOL> elif val < <NUM_LIT> : <EOL> buf [ offset ] = ( val >> <NUM_LIT> & <NUM_LIT> ) | <NUM_LIT> <EOL> buf [ offset + <NUM_LIT:1> ] = ( val >> <NUM_LIT:7> & <NUM_LIT> ) | <NUM_LIT> <EOL> buf [ offset + <NUM_LIT:2> ] = val & <NUM_LIT> <EOL> offset += <NUM_LIT:3> <EOL> elif val < <NUM_LIT> : <EOL> buf [ offset ] = ( val >> <NUM_LIT> & <NUM_LIT> ) | <NUM_LIT> <EOL> buf [ offset + <NUM_LIT:1> ] = ( val >> <NUM_LIT:15> & <NUM_LIT> ) | <NUM_LIT> <EOL> buf [ offset + <NUM_LIT:2> ] = ( val >> <NUM_LIT:8> & <NUM_LIT> ) | <NUM_LIT> <EOL> buf [ offset + <NUM_LIT:3> ] = val & <NUM_LIT> <EOL> offset += <NUM_LIT:4> <EOL> return offset <EOL> @ classmethod <EOL> def read ( cls , fd ) : <EOL> rval , byte_count = <NUM_LIT:0> , <NUM_LIT:0> <EOL> byte = U8 . read ( fd ) <EOL> while ( byte & <NUM_LIT> ) != <NUM_LIT:0> and byte_count < <NUM_LIT:3> : <EOL> rval <<= <NUM_LIT:7> <EOL> rval |= byte & <NUM_LIT> <EOL> byte = U8 . read ( fd ) <EOL> byte_count += <NUM_LIT:1> <EOL> if byte_count < <NUM_LIT:3> : <EOL> rval <<= <NUM_LIT:7> <EOL> rval |= byte & <NUM_LIT> <EOL> else : <EOL> rval <<= <NUM_LIT:8> <EOL> rval |= byte & <NUM_LIT> <EOL> if ( rval & <NUM_LIT> ) != <NUM_LIT:0> : <EOL> rval -= <NUM_LIT> <EOL> return rval <EOL> class AMF3String ( String ) : <EOL> @ classmethod <EOL> def size ( cls , val , cache ) : <EOL> data = String . pack ( val , "<STR_LIT:utf8>" , "<STR_LIT:ignore>" ) <EOL> size = len ( data ) <EOL> if size == <NUM_LIT:0> : <EOL> return U8 . size <EOL> elif val in cache : <EOL> index = cache . index ( val ) <EOL> return AMF3Integer . size ( index << <NUM_LIT:1> ) <EOL> else : <EOL> cache . append ( val ) <EOL> return AMF3Integer . size ( size << <NUM_LIT:1> | <NUM_LIT:1> ) + size <EOL> @ classmethod <EOL> def pack ( cls , val , cache ) : <EOL> data = String . pack ( val , "<STR_LIT:utf8>" , "<STR_LIT:ignore>" ) <EOL> size = len ( data ) <EOL> if size == <NUM_LIT:0> : <EOL> return U8 ( AMF3_EMPTY_STRING ) <EOL> elif val in cache : <EOL> index = cache . index ( val ) <EOL> return AMF3Integer ( index << <NUM_LIT:1> ) <EOL> else : <EOL> cache . append ( val ) <EOL> chunks = [ ] <EOL> chunks . append ( AMF3Integer ( size << <NUM_LIT:1> | <NUM_LIT:1> ) ) <EOL> chunks . append ( data ) <EOL> return b"<STR_LIT>" . join ( chunks ) <EOL> @ classmethod <EOL> def read ( cls , fd , cache ) : <EOL> header = AMF3Integer . read ( fd ) <EOL> if ( header & <NUM_LIT:1> ) == <NUM_LIT:0> : <EOL> index = header >> <NUM_LIT:1> <EOL> return cache [ index ] <EOL> else : <EOL> size = header >> <NUM_LIT:1> <EOL> data = fd . read ( size ) <EOL> rval = data . decode ( "<STR_LIT:utf8>" , "<STR_LIT:ignore>" ) <EOL> if len ( data ) > <NUM_LIT:0> : <EOL> cache . append ( rval ) <EOL> return rval <EOL> class AMF3ObjectBase ( object ) : <EOL> __dynamic__ = False <EOL> __externalizable__ = False <EOL> __members__ = [ ] <EOL> _registry = { } <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> for key , value in kwargs . items ( ) : <EOL> setattr ( self , key , value ) <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" . format ( self . __class__ . __name__ , self . __dict__ ) <EOL> @ classmethod <EOL> def register ( cls , name ) : <EOL> def deco ( amfcls ) : <EOL> amfcls . __name__ = name <EOL> if not amfcls . __members__ : <EOL> amfcls . __members__ = getargspec ( amfcls . __init__ ) . args [ <NUM_LIT:1> : ] <EOL> cls . _registry [ name ] = amfcls <EOL> return amfcls <EOL> return deco <EOL> @ classmethod <EOL> def lookup ( cls , name ) : <EOL> return cls . _registry . get ( name , None ) <EOL> @ classmethod <EOL> def create ( cls , name , externalizable , dynamic , members ) : <EOL> if is_py2 : <EOL> name = name . encode ( "<STR_LIT:utf8>" ) <EOL> amfcls = type ( name , ( cls , ) , { } ) <EOL> amfcls . __externalizable__ = externalizable <EOL> amfcls . __members__ = members <EOL> return amfcls <EOL> class AMF3Object ( OrderedDict , AMF3ObjectBase ) : <EOL> __dynamic__ = True <EOL> class AMF3ObjectPacker ( DynamicType , AMF3Type ) : <EOL> __identifier__ = AMF3_TYPE_OBJECT <EOL> @ classmethod <EOL> def size ( cls , val , str_cache , object_cache , traits_cache ) : <EOL> if val in object_cache : <EOL> index = object_cache . index ( val ) <EOL> return AMF3Integer . size ( index << <NUM_LIT:1> ) <EOL> else : <EOL> object_cache . append ( val ) <EOL> size = <NUM_LIT:0> <EOL> traits = type ( val ) <EOL> if traits in traits_cache : <EOL> index = traits_cache . index ( traits ) <EOL> size += AMF3Integer . size ( index << <NUM_LIT:2> | <NUM_LIT> ) <EOL> else : <EOL> header = <NUM_LIT> <EOL> if traits . __dynamic__ : <EOL> header |= <NUM_LIT> << <NUM_LIT:2> <EOL> if traits . __externalizable__ : <EOL> header |= <NUM_LIT> << <NUM_LIT:2> <EOL> header |= ( len ( traits . __members__ ) ) << <NUM_LIT:4> <EOL> size += AMF3Integer . size ( header ) <EOL> if isinstance ( val , AMF3Object ) : <EOL> size += U8 . size <EOL> else : <EOL> size += AMF3String . size ( traits . __name__ , cache = str_cache ) <EOL> traits_cache . append ( traits ) <EOL> for member in traits . __members__ : <EOL> size += AMF3String . size ( member , cache = str_cache ) <EOL> for member in traits . __members__ : <EOL> value = getattr ( val , member ) <EOL> size += AMF3Value . size ( value , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> if traits . __dynamic__ : <EOL> if isinstance ( val , AMF3Object ) : <EOL> iterator = val . items ( ) <EOL> else : <EOL> iterator = val . __dict__ . items ( ) <EOL> for key , value in iterator : <EOL> if key in traits . __members__ : <EOL> continue <EOL> size += AMF3String . size ( key , cache = str_cache ) <EOL> size += AMF3Value . size ( value , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> size += U8 . size <EOL> return size <EOL> @ classmethod <EOL> def pack ( cls , val , str_cache , object_cache , traits_cache ) : <EOL> chunks = [ ] <EOL> if val in object_cache : <EOL> index = object_cache . index ( val ) <EOL> return AMF3Integer ( index << <NUM_LIT:1> ) <EOL> else : <EOL> object_cache . append ( val ) <EOL> chunks = [ ] <EOL> traits = type ( val ) <EOL> if traits in traits_cache : <EOL> index = traits_cache . index ( traits ) <EOL> chunks . append ( AMF3Integer ( index << <NUM_LIT:2> | <NUM_LIT> ) ) <EOL> else : <EOL> header = <NUM_LIT> <EOL> if traits . __dynamic__ : <EOL> header |= <NUM_LIT> << <NUM_LIT:2> <EOL> if traits . __externalizable__ : <EOL> header |= <NUM_LIT> << <NUM_LIT:2> <EOL> header |= ( len ( traits . __members__ ) ) << <NUM_LIT:4> <EOL> chunks . append ( AMF3Integer ( header ) ) <EOL> if isinstance ( val , AMF3Object ) : <EOL> chunks . append ( U8 ( AMF3_EMPTY_STRING ) ) <EOL> else : <EOL> chunks . append ( AMF3String ( traits . __name__ , cache = str_cache ) ) <EOL> traits_cache . append ( traits ) <EOL> for member in traits . __members__ : <EOL> chunks . append ( AMF3String ( member , cache = str_cache ) ) <EOL> for member in traits . __members__ : <EOL> value = getattr ( val , member ) <EOL> value = AMF3Value . pack ( value , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> chunks . append ( value ) <EOL> if traits . __dynamic__ : <EOL> if isinstance ( val , AMF3Object ) : <EOL> iterator = val . items ( ) <EOL> else : <EOL> iterator = val . __dict__ . items ( ) <EOL> for key , value in iterator : <EOL> if key in traits . __members__ : <EOL> continue <EOL> key = AMF3String ( key , cache = str_cache ) <EOL> value = AMF3Value . pack ( value , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> chunks . append ( key ) <EOL> chunks . append ( value ) <EOL> chunks . append ( U8 ( AMF3_CLOSE_DYNAMIC_ARRAY ) ) <EOL> return b"<STR_LIT>" . join ( chunks ) <EOL> @ classmethod <EOL> def read ( cls , fd , str_cache , object_cache , traits_cache ) : <EOL> header = AMF3Integer . read ( fd ) <EOL> obj = None <EOL> if ( header & <NUM_LIT:1> ) == <NUM_LIT:0> : <EOL> index = header >> <NUM_LIT:1> <EOL> obj = object_cache [ index ] <EOL> else : <EOL> header >>= <NUM_LIT:1> <EOL> if ( header & <NUM_LIT:1> ) == <NUM_LIT:0> : <EOL> index = header >> <NUM_LIT:1> <EOL> traits = traits_cache [ index ] <EOL> else : <EOL> externalizable = ( header & <NUM_LIT:2> ) != <NUM_LIT:0> <EOL> dynamic = ( header & <NUM_LIT:4> ) != <NUM_LIT:0> <EOL> members_len = header >> <NUM_LIT:3> <EOL> class_name = AMF3String . read ( fd , cache = str_cache ) <EOL> members = [ ] <EOL> for i in range ( members_len ) : <EOL> member_name = AMF3String . read ( fd , cache = str_cache ) <EOL> members . append ( member_name ) <EOL> if len ( class_name ) == <NUM_LIT:0> : <EOL> traits = AMF3Object <EOL> elif AMF3ObjectBase . lookup ( class_name ) : <EOL> traits = AMF3ObjectBase . lookup ( class_name ) <EOL> traits . __members__ = members <EOL> traits . __dynamic__ = dynamic <EOL> traits_cache . append ( traits ) <EOL> else : <EOL> traits = AMF3ObjectBase . create ( class_name , externalizable , <EOL> dynamic , members ) <EOL> traits_cache . append ( traits ) <EOL> values = OrderedDict ( ) <EOL> for member in traits . __members__ : <EOL> value = AMF3Value . read ( fd , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> values [ member ] = value <EOL> if traits . __dynamic__ : <EOL> key = AMF3String . read ( fd , cache = str_cache ) <EOL> while len ( key ) > <NUM_LIT:0> : <EOL> value = AMF3Value . read ( fd , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> values [ key ] = value <EOL> key = AMF3String . read ( fd , cache = str_cache ) <EOL> if traits == AMF3Object : <EOL> obj = traits ( values ) <EOL> else : <EOL> obj = traits ( ** values ) <EOL> return obj <EOL> class AMF3Array ( OrderedDict ) : <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> if args and isinstance ( args [ <NUM_LIT:0> ] , list ) : <EOL> OrderedDict . __init__ ( self , ** kwargs ) <EOL> for i , value in enumerate ( args [ <NUM_LIT:0> ] ) : <EOL> self [ i ] = value <EOL> else : <EOL> OrderedDict . __init__ ( self , * args , ** kwargs ) <EOL> def dense_keys ( self ) : <EOL> dense_keys = [ ] <EOL> for i in range ( len ( self ) ) : <EOL> if i in self : <EOL> dense_keys . append ( i ) <EOL> return dense_keys <EOL> def dense_values ( self ) : <EOL> for key in self . dense_keys ( ) : <EOL> yield self [ key ] <EOL> class AMF3ArrayPacker ( DynamicType , AMF3Type ) : <EOL> __identifier__ = AMF3_TYPE_ARRAY <EOL> @ classmethod <EOL> def size ( cls , val , str_cache , object_cache , traits_cache ) : <EOL> if val in object_cache : <EOL> index = object_cache . index ( val ) <EOL> return AMF3Integer . size ( index << <NUM_LIT:1> ) <EOL> else : <EOL> object_cache . append ( val ) <EOL> size = <NUM_LIT:0> <EOL> if isinstance ( val , AMF3Array ) : <EOL> dense_keys = val . dense_keys ( ) <EOL> length = len ( dense_keys ) <EOL> else : <EOL> length = len ( val ) <EOL> dense_keys = list ( range ( length ) ) <EOL> header = length << <NUM_LIT:1> | <NUM_LIT:1> <EOL> size += AMF3Integer . size ( header ) <EOL> if isinstance ( val , AMF3Array ) : <EOL> for key , value in val . items ( ) : <EOL> if key in dense_keys : <EOL> continue <EOL> size += AMF3String . size ( key , cache = str_cache ) <EOL> size += AMF3Value . size ( value , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> size += U8 . size <EOL> for key in dense_keys : <EOL> value = val [ key ] <EOL> size += AMF3Value . size ( value , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> return size <EOL> @ classmethod <EOL> def pack ( cls , val , str_cache , object_cache , traits_cache ) : <EOL> if val in object_cache : <EOL> index = object_cache . index ( val ) <EOL> return AMF3Integer ( index << <NUM_LIT:1> ) <EOL> else : <EOL> object_cache . append ( val ) <EOL> chunks = [ ] <EOL> if isinstance ( val , AMF3Array ) : <EOL> dense_keys = val . dense_keys ( ) <EOL> length = len ( dense_keys ) <EOL> else : <EOL> length = len ( val ) <EOL> dense_keys = list ( range ( length ) ) <EOL> header = length << <NUM_LIT:1> | <NUM_LIT:1> <EOL> chunks . append ( AMF3Integer ( header ) ) <EOL> if isinstance ( val , AMF3Array ) : <EOL> for key , value in val . items ( ) : <EOL> if key in dense_keys : <EOL> continue <EOL> chunks . append ( AMF3String ( key , cache = str_cache ) ) <EOL> value = AMF3Value . pack ( value , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> chunks . append ( value ) <EOL> chunks . append ( U8 ( AMF3_CLOSE_DYNAMIC_ARRAY ) ) <EOL> for key in dense_keys : <EOL> value = val [ key ] <EOL> value = AMF3Value . pack ( value , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> chunks . append ( value ) <EOL> return b"<STR_LIT>" . join ( chunks ) <EOL> @ classmethod <EOL> def read ( cls , fd , str_cache , object_cache , traits_cache ) : <EOL> header = AMF3Integer . read ( fd ) <EOL> obj = None <EOL> if ( header & <NUM_LIT:1> ) == <NUM_LIT:0> : <EOL> index = header >> <NUM_LIT:1> <EOL> obj = object_cache [ index ] <EOL> else : <EOL> header >>= <NUM_LIT:1> <EOL> obj = AMF3Array ( ) <EOL> object_cache . append ( obj ) <EOL> key = AMF3String . read ( fd , cache = str_cache ) <EOL> while len ( key ) > <NUM_LIT:0> : <EOL> value = AMF3Value . read ( fd , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> obj [ key ] = value <EOL> key = AMF3String . read ( fd , cache = str_cache ) <EOL> for i in range ( header ) : <EOL> value = AMF3Value . read ( fd , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> obj [ i ] = value <EOL> return obj <EOL> class AMF3Date ( object ) : <EOL> def __init__ ( self , time ) : <EOL> self . time = time <EOL> class AMF3DatePacker ( DynamicType , AMF3Type ) : <EOL> __identifier__ = AMF3_TYPE_ARRAY <EOL> @ classmethod <EOL> def size ( cls , val , cache ) : <EOL> if val in cache : <EOL> index = cache . index ( val ) <EOL> return AMF3Integer . size ( index << <NUM_LIT:1> ) <EOL> else : <EOL> cache . append ( val ) <EOL> return AMF3Double . size + U8 . size <EOL> @ classmethod <EOL> def pack ( cls , val , cache ) : <EOL> if val in cache : <EOL> index = cache . index ( val ) <EOL> return AMF3Integer ( index << <NUM_LIT:1> ) <EOL> else : <EOL> cache . append ( val ) <EOL> chunks = [ U8 ( AMF3_TYPE_NULL ) , <EOL> AMF3Double ( val . time ) ] <EOL> return b"<STR_LIT>" . join ( chunks ) <EOL> @ classmethod <EOL> def read ( cls , fd , cache ) : <EOL> header = AMF3Integer . read ( fd ) <EOL> if ( header & <NUM_LIT:1> ) == <NUM_LIT:0> : <EOL> index = header >> <NUM_LIT:1> <EOL> return cache [ index ] <EOL> else : <EOL> time = AMF3Double . read ( fd ) <EOL> date = AMF3Date ( time ) <EOL> cache . append ( date ) <EOL> return date <EOL> class AMF3Value ( DynamicType ) : <EOL> PrimitiveReaders = { <EOL> AMF3_TYPE_DOUBLE : AMF3Double , <EOL> } <EOL> DynamicReaders = { <EOL> AMF3_TYPE_INTEGER : AMF3Integer , <EOL> } <EOL> Readers = PrimitiveReaders . copy ( ) <EOL> Readers . update ( DynamicReaders ) <EOL> @ classmethod <EOL> def size ( cls , val , str_cache = None , object_cache = None , traits_cache = None ) : <EOL> if str_cache is None : <EOL> str_cache = [ ] <EOL> if object_cache is None : <EOL> object_cache = [ ] <EOL> if traits_cache is None : <EOL> traits_cache = [ ] <EOL> size = U8 . size <EOL> if isinstance ( val , bool ) and val in ( False , True ) : <EOL> pass <EOL> elif val is None : <EOL> pass <EOL> elif isinstance ( val , integer_types ) : <EOL> if val < AMF3_MIN_INTEGER or val > AMF3_MAX_INTEGER : <EOL> size += AMF3Double . size <EOL> else : <EOL> size += AMF3Integer . size ( val ) <EOL> elif isinstance ( val , float ) : <EOL> size += AMF3Double . size <EOL> elif isinstance ( val , ( AMF3Array , list ) ) : <EOL> size += AMF3ArrayPacker . size ( val , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> elif isinstance ( val , string_types ) : <EOL> size += AMF3String . size ( val , cache = str_cache ) <EOL> elif isinstance ( val , AMF3ObjectBase ) : <EOL> size += AMF3ObjectPacker . size ( val , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> elif isinstance ( val , AMF3Date ) : <EOL> size += AMF3DatePacker . size ( val , cache = object_cache ) <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" . format ( type ( val ) ) ) <EOL> return size <EOL> @ classmethod <EOL> def pack ( cls , val , str_cache = None , object_cache = None , traits_cache = None ) : <EOL> if str_cache is None : <EOL> str_cache = [ ] <EOL> if object_cache is None : <EOL> object_cache = [ ] <EOL> if traits_cache is None : <EOL> traits_cache = [ ] <EOL> chunks = [ ] <EOL> if isinstance ( val , bool ) : <EOL> if val is False : <EOL> chunks . append ( U8 ( AMF3_TYPE_FALSE ) ) <EOL> elif val is True : <EOL> chunks . append ( U8 ( AMF3_TYPE_TRUE ) ) <EOL> elif val is None : <EOL> chunks . append ( U8 ( AMF3_TYPE_NULL ) ) <EOL> elif isinstance ( val , integer_types ) : <EOL> if val < AMF3_MIN_INTEGER or val > AMF3_MAX_INTEGER : <EOL> chunks . append ( U8 ( AMF3_TYPE_DOUBLE ) ) <EOL> chunks . append ( AMF3Double ( val ) ) <EOL> else : <EOL> chunks . append ( U8 ( AMF3_TYPE_INTEGER ) ) <EOL> chunks . append ( AMF3Integer ( val ) ) <EOL> elif isinstance ( val , float ) : <EOL> chunks . append ( U8 ( AMF3_TYPE_DOUBLE ) ) <EOL> chunks . append ( AMF3Double ( val ) ) <EOL> elif isinstance ( val , ( AMF3Array , list ) ) : <EOL> chunks . append ( U8 ( AMF3_TYPE_ARRAY ) ) <EOL> chunks . append ( AMF3ArrayPacker . pack ( val , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) ) <EOL> elif isinstance ( val , string_types ) : <EOL> chunks . append ( U8 ( AMF3_TYPE_STRING ) ) <EOL> chunks . append ( AMF3String . pack ( val , cache = str_cache ) ) <EOL> elif isinstance ( val , AMF3ObjectBase ) : <EOL> chunks . append ( U8 ( AMF3_TYPE_OBJECT ) ) <EOL> chunks . append ( AMF3ObjectPacker . pack ( val , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) ) <EOL> elif isinstance ( val , AMF3Date ) : <EOL> chunks . append ( U8 ( AMF3_TYPE_DATE ) ) <EOL> chunks . append ( AMF3DatePacker . pack ( val , cache = object_cache ) ) <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" . format ( type ( val ) ) ) <EOL> return b"<STR_LIT>" . join ( chunks ) <EOL> @ classmethod <EOL> def read ( cls , fd , str_cache = None , object_cache = None , traits_cache = None ) : <EOL> type_ = U8 . read ( fd ) <EOL> if str_cache is None : <EOL> str_cache = [ ] <EOL> if object_cache is None : <EOL> object_cache = [ ] <EOL> if traits_cache is None : <EOL> traits_cache = [ ] <EOL> if type_ == AMF3_TYPE_UNDEFINED or type_ == AMF3_TYPE_NULL : <EOL> return None <EOL> elif type_ == AMF3_TYPE_FALSE : <EOL> return False <EOL> elif type_ == AMF3_TYPE_TRUE : <EOL> return True <EOL> elif type_ == AMF3_TYPE_STRING : <EOL> return AMF3String . read ( fd , cache = str_cache ) <EOL> elif type_ == AMF3_TYPE_ARRAY : <EOL> return AMF3ArrayPacker . read ( fd , str_cache = str_cache , <EOL> object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> elif type_ == AMF3_TYPE_OBJECT : <EOL> return AMF3ObjectPacker . read ( fd , str_cache = str_cache , object_cache = object_cache , <EOL> traits_cache = traits_cache ) <EOL> elif type_ == AMF3_TYPE_DATE : <EOL> return AMF3DatePacker . read ( fd , cache = object_cache ) <EOL> elif type_ in cls . Readers : <EOL> return cls . Readers [ type_ ] . read ( fd ) <EOL> else : <EOL> raise IOError ( "<STR_LIT>" . format ( hex ( type_ ) ) ) </s>
