3 SÉLj~oã@sðdZdZddlZddlZddlmZdZe Zdd„Zdd „Z d d „Z d d „Z dd„Z dd„Z e e ƒZZZe eƒZZe e ejƒZZe dƒZZZe dƒZZZe dƒZdd„Zdd„Zdd„Zdd„Z dd„Z!dd „Z"d!d"„Z#d#d$„Z$e#ƒZ%e$ƒZ&d%d&„Z'd'd(„Z(d)d*„Z)d+d,„Z*d-d.„Z+d/d0„Z,e)ej-e&e ƒZ.Z/Z0e)ej-e%eƒZ1Z2e*ej-e%eejƒZ3Z4e+ej5d1ƒZ6e+ej7d2ƒZ8e+ej5d3ƒZ9e+ej7d4ƒZ:e,ej5d5ƒZ;e,ej7d6ƒZd;d<„Z?d=d>„Z@d?d@„ZAdAdB„ZBdCdD„ZCdS)Ea­Code for encoding protocol message primitives. Contains the logic for encoding every logical protocol field type into one of the 5 physical wire types. This code is designed to push the Python interpreter's performance to the limits. The basic idea is that at startup time, for every field (i.e. every FieldDescriptor) we construct two functions: a "sizer" and an "encoder". The sizer takes a value of this field's type and computes its byte size. The encoder takes a writer function and a value. It encodes the value into byte strings and invokes the writer function to write those strings. Typically the writer function is the write() method of a BytesIO. We try to do as much work as possible when constructing the writer and the sizer rather than when calling them. In particular: * We copy any needed global functions to local variables, so that we do not need to do costly global table lookups at runtime. * Similarly, we try to do any attribute lookups at startup time if possible. * Every field's tag is encoded to bytes at startup, since it can't change at runtime. * Whatever component of the field size we can compute at startup, we do. * We *avoid* sharing code if doing so would make the code slower and not sharing does not burden us too much. For example, encoders for repeated fields do not just call the encoders for singular fields in a loop because this would add an extra function call overhead for every loop iteration; instead, we manually inline the single-value encoder into the loop. * If a Python function lacks a return statement, Python actually generates instructions to pop the result of the last statement off the stack, push None onto the stack, and then return that. If we really don't care what value is returned, then we can save two instructions by returning the result of the last statement. It looks funny but it helps. * We assume that type and bounds checking has happened at a higher level. z kenton@google.com (Kenton Varda)éN)Ú wire_formatgðcCsp|dkr dS|dkrdS|dkr$dS|dkr0dS|d kr.SpecificSizer..PackedFieldSizecs*ˆt|ƒ}x|D]}|ˆ|ƒ7}qW|S)N)Úlen)rrr)rrrrÚRepeatedFieldSize�s  z>_SimpleSizer..SpecificSizer..RepeatedFieldSizecs ˆˆ|ƒS)Nr)r)rrrrÚ FieldSize”sz6_SimpleSizer..SpecificSizer..FieldSize)rr)rÚ is_repeatedÚ is_packedrrr)r)rrrÚ SpecificSizer‚sz#_SimpleSizer..SpecificSizerr)rr!r)rrÚ _SimpleSizer~s r"cs‡‡fdd„}|S)z‘Like SimpleSizer, but modify_value is invoked on each value before it is passed to compute_value_size. modify_value is typically ZigZagEncode.csVt|ƒ‰|r&t‰‡‡‡‡fdd„}|S|r>‡‡‡fdd„}|S‡‡‡fdd„}|SdS)Ncs2d}x|D]}|ˆˆ|ƒƒ7}q W|ˆ|ƒˆS)Nrr)rrr)rrÚ modify_valuerrrr£s z>_ModifiedSizer..SpecificSizer..PackedFieldSizecs.ˆt|ƒ}x|D]}|ˆˆ|ƒƒ7}qW|S)N)r)rrr)rr#rrrrªs  z@_ModifiedSizer..SpecificSizer..RepeatedFieldSizecsˆˆˆ|ƒƒS)Nr)r)rr#rrrr±sz8_ModifiedSizer..SpecificSizer..FieldSize)rr)rrr rrr)rr#)rrrr!Ÿsz%_ModifiedSizer..SpecificSizerr)rr#r!r)rr#rÚ_ModifiedSizer›sr$cs‡fdd„}|S)zWLike _SimpleSizer except for a fixed-size field. The input is the size of one value.cs\t|ƒ‰|r$t‰‡‡‡fdd„}|S|r@ˆˆ‰‡fdd„}|Sˆˆ‰‡fdd„}|SdS)Ncst|ƒˆ}|ˆ|ƒˆS)N)r)rr)rrÚ value_sizerrrÀs z;_FixedSizer..SpecificSizer..PackedFieldSizecs t|ƒˆS)N)r)r)Ú element_sizerrrÆsz=_FixedSizer..SpecificSizer..RepeatedFieldSizecsˆS)Nr)r)Ú field_sizerrrËsz5_FixedSizer..SpecificSizer..FieldSize)rr)rrr rrr)r%)r&r'rrrr!¼s  z"_FixedSizer..SpecificSizerr)r%r!r)r%rÚ _FixedSizer¸s r(rr rcs@t|ƒ‰t‰t‰|r(‡‡‡fdd„}|S‡‡‡fdd„}|SdS)z#Returns a sizer for a string field.cs<ˆt|ƒ}x*|D]"}ˆ|jdƒƒ}|ˆ|ƒ|7}qW|S)Nzutf-8)rÚencode)rrrÚl)rÚ local_lenrrrrîs   z&StringSizer..RepeatedFieldSizecsˆ|jdƒƒ}ˆˆ|ƒ|S)Nzutf-8)r))rr*)rr+rrrröszStringSizer..FieldSizeN)rrr)rrr rrr)rr+rrÚ StringSizeræsr,cs@t|ƒ‰t‰t‰|r(‡‡‡fdd„}|S‡‡‡fdd„}|SdS)z"Returns a sizer for a bytes field.cs6ˆt|ƒ}x$|D]}ˆ|ƒ}|ˆ|ƒ|7}qW|S)N)r)rrrr*)rr+rrrrs   z%BytesSizer..RepeatedFieldSizecsˆ|ƒ}ˆˆ|ƒ|S)Nr)rr*)rr+rrrr szBytesSizer..FieldSizeN)rrr)rrr rrr)rr+rrÚ BytesSizerüsr-cs4t|ƒd‰|r ‡fdd„}|S‡fdd„}|SdS)z"Returns a sizer for a group field.rcs*ˆt|ƒ}x|D]}||jƒ7}qW|S)N)rÚByteSize)rrr)rrrrs  z%GroupSizer..RepeatedFieldSizecs ˆ|jƒS)N)r.)r)rrrrszGroupSizer..FieldSizeN)r)rrr rrr)rrÚ GroupSizers    r/cs8t|ƒ‰t‰|r"‡‡fdd„}|S‡‡fdd„}|SdS)z$Returns a sizer for a message field.cs6ˆt|ƒ}x$|D]}|jƒ}|ˆ|ƒ|7}qW|S)N)rr.)rrrr*)rrrrr+s   z'MessageSizer..RepeatedFieldSizecs|jƒ}ˆˆ|ƒ|S)N)r.)rr*)rrrrr3szMessageSizer..FieldSizeN)rr)rrr rrr)rrrÚ MessageSizer$sr0cs:tdƒdtdƒt|ƒtdƒ‰t‰‡‡fdd„}|S)zìReturns a sizer for extensions of MessageSet. The message set message looks like this: message MessageSet { repeated group Item = 1 { required int32 type_id = 2; required string message = 3; } } rrrcs|jƒ}ˆˆ|ƒ|S)N)r.)rr*)rÚ static_sizerrrLsz&MessageSetItemSizer..FieldSize)rr)rrr)rr1rÚMessageSetItemSizer=s  r2cs(|j‰t|jddƒ‰‡‡‡fdd„}|S)z Returns a sizer for a map field.FcsDd}x:|D]2}||}ˆj||d�}|ˆ|ƒ7}ˆr |jƒq W|S)Nr)Úkeyr)Ú_concrete_classr.)Z map_valueZtotalr3rÚ entry_msg)Úis_message_mapÚ message_sizerÚ message_typerrr_s   zMapSizer..FieldSize)r8r0Únumber)Úfield_descriptorr6rr)r6r7r8rÚMapSizerWsr;cCs dd„}|S)zBReturn an encoder for a basic varint value (does not include tag).cSsJ|d@}|dL}x*|r:|tjd|Bƒƒ|d@}|dL}qW|tj|ƒƒS)Nrr é€)ÚsixÚint2byte)ÚwriterÚunused_deterministicÚbitsrrrÚ EncodeVarintws z$_VarintEncoder..EncodeVarintr)rBrrrÚ_VarintEncoderts rCcCs dd„}|S)zKReturn an encoder for a basic signed varint value (does not include tag).cSsZ|dkr|d7}|d@}|dL}x*|rJ|tjd|Bƒƒ|d@}|dL}q"W|tj|ƒƒS)Nrré@rr r<l)r=r>)r?rr@rArrrÚEncodeSignedVarint‡s z0_SignedVarintEncoder..EncodeSignedVarintr)rErrrÚ_SignedVarintEncoderƒs rFcCsg}t|j|dƒdj|ƒS)z€Encode the given integer as a varint and return the bytes. This is only called at startup time so it doesn't need to be fast.Tó)Ú _EncodeVarintÚappendÚjoin)rÚpiecesrrrÚ _VarintBytes™srLcCstjttj||ƒƒƒS)zCEncode the given tag and return the bytes. Only called at startup.)r=Z binary_typerLrr)rÚ wire_typerrrÚTagBytes¢srNcs‡‡‡fdd„}|S)a_Return a constructor for an encoder for fields of a particular type. Args: wire_type: The field's wire type, for encoding tags. encode_value: A function which encodes an individual value, e.g. _EncodeVarint(). compute_value_size: A function which computes the size of an individual value, e.g. _VarintSize(). csj|r*t|tjƒ‰t‰‡‡‡‡fdd„}|S|rJt|ˆƒ‰‡‡fdd„}|St|ˆƒ‰‡‡fdd„}|SdS)NcsP|ˆƒd}x|D]}|ˆ|ƒ7}qWˆ|||ƒx|D]}ˆ|||ƒq8WdS)Nrr)r?rÚ deterministicÚsizer)rÚ encode_valueÚlocal_EncodeVarintÚ tag_bytesrrÚEncodePackedField»s   zB_SimpleEncoder..SpecificEncoder..EncodePackedFieldcs&x |D]}|ˆƒˆ|||ƒqWdS)Nr)r?rrOr)rQrSrrÚEncodeRepeatedFieldÆs zD_SimpleEncoder..SpecificEncoder..EncodeRepeatedFieldcs|ˆƒˆ|||ƒS)Nr)r?rrO)rQrSrrÚ EncodeFieldÍsz<_SimpleEncoder..SpecificEncoder..EncodeField)rNrÚWIRETYPE_LENGTH_DELIMITEDrH)rrr rTrUrV)rrQrM)rRrSrÚSpecificEncoder·s   z'_SimpleEncoder..SpecificEncoderr)rMrQrrXr)rrQrMrÚ_SimpleEncoder¬s rYcs‡‡‡‡fdd„}|S)z“Like SimpleEncoder but additionally invokes modify_value on every value before passing it to encode_value. Usually modify_value is ZigZagEncode.csp|r,t|tjƒ‰t‰‡‡‡‡‡fdd„}|S|rNt|ˆƒ‰‡‡‡fdd„}|St|ˆƒ‰‡‡‡fdd„}|SdS)NcsX|ˆƒd}x|D]}|ˆˆ|ƒƒ7}qWˆ|||ƒx|D]}ˆ|ˆ|ƒ|ƒq.SpecificEncoder..EncodePackedFieldcs*x$|D]}|ˆƒˆ|ˆ|ƒ|ƒqWdS)Nr)r?rrOr)rQr#rSrrrUès zF_ModifiedEncoder..SpecificEncoder..EncodeRepeatedFieldcs|ˆƒˆ|ˆ|ƒ|ƒS)Nr)r?rrO)rQr#rSrrrVïsz>_ModifiedEncoder..SpecificEncoder..EncodeField)rNrrWrH)rrr rTrUrV)rrQr#rM)rRrSrrXÙs   z)_ModifiedEncoder..SpecificEncoderr)rMrQrr#rXr)rrQr#rMrÚ_ModifiedEncoderÕsrZcstjˆƒ‰‡‡‡fdd„}|S)z¿Return a constructor for an encoder for a fixed-width field. Args: wire_type: The field's wire type, for encoding tags. format: The format string to pass to struct.pack(). csvtj‰|r2t|tjƒ‰t‰‡‡‡‡‡fdd„}|S|rTt|ˆƒ‰‡‡‡fdd„}|St|ˆƒ‰‡‡‡fdd„}|SdS)Ncs<|ˆƒˆ|t|ƒˆ|ƒx|D]}|ˆˆ|ƒƒq"WdS)N)r)r?rrOr)ÚformatrRÚlocal_struct_packrSr%rrrTs zF_StructPackEncoder..SpecificEncoder..EncodePackedFieldcs(x"|D]}|ˆƒ|ˆˆ|ƒƒqWdS)Nr)r?rr@r)r[r\rSrrrUs zH_StructPackEncoder..SpecificEncoder..EncodeRepeatedFieldcs|ˆƒ|ˆˆ|ƒƒS)Nr)r?rr@)r[r\rSrrrVsz@_StructPackEncoder..SpecificEncoder..EncodeField)ÚstructÚpackrNrrWrH)rrr rTrUrV)r[r%rM)rRr\rSrrXs   z+_StructPackEncoder..SpecificEncoder)r]Úcalcsize)rMr[rXr)r[r%rMrÚ_StructPackEncoder÷s r`csPtjˆƒ‰ˆdkrdd„‰nˆdkr.dd„‰n tdˆƒ‚‡‡‡‡fdd„}|S) aqReturn a constructor for an encoder for float fields. This is like StructPackEncoder, but catches errors that may be due to passing non-finite floating-point values to struct.pack, and makes a second attempt to encode those values. Args: wire_type: The field's wire type, for encoding tags. format: The format string to pass to struct.pack(). rcSs<|tkr|dƒn&|tkr$|dƒn||kr6|dƒn‚dS)Ns€s€ÿsÀ)Ú_POS_INFÚ_NEG_INF)r?rrrrÚEncodeNonFiniteOrRaise+s   z5_FloatingPointEncoder..EncodeNonFiniteOrRaiser cSs<|tkr|dƒn&|tkr$|dƒn||kr6|dƒn‚dS)Nsðsðÿsø)rarb)r?rrrrrc6s   zGCan't encode floating-point values that are %d bytes long (only 4 or 8)cs|tj‰|r4t|tjƒ‰t‰‡‡‡‡‡‡fdd„}|S|rXt|ˆƒ‰‡‡‡‡fdd„}|St|ˆƒ‰‡‡‡‡fdd„}|SdS)Nc s`|ˆƒˆ|t|ƒˆ|ƒx>|D]6}y|ˆˆ|ƒƒWq"tk rVˆ||ƒYq"Xq"WdS)N)rÚ SystemError)r?rrOr)rcr[rRr\rSr%rrrTHs zI_FloatingPointEncoder..SpecificEncoder..EncodePackedFieldc sLxF|D]>}|ˆƒy|ˆˆ|ƒƒWqtk rBˆ||ƒYqXqWdS)N)rd)r?rr@r)rcr[r\rSrrrUUs  zK_FloatingPointEncoder..SpecificEncoder..EncodeRepeatedFieldc s>|ˆƒy|ˆˆ|ƒƒWntk r8ˆ||ƒYnXdS)N)rd)r?rr@)rcr[r\rSrrrV_s zC_FloatingPointEncoder..SpecificEncoder..EncodeField)r]r^rNrrWrH)rrr rTrUrV)rcr[r%rM)rRr\rSrrXCs    z._FloatingPointEncoder..SpecificEncoder)r]r_Ú ValueError)rMr[rXr)rcr[r%rMrÚ_FloatingPointEncoders   $rfz.EncodePackedFieldcs0x*|D]"}|ˆƒ|r |ˆƒq|ˆƒqWdS)Nr)r?rr@r)rirSrjrrrU˜s   z(BoolEncoder..EncodeRepeatedFieldcs|ˆƒ|r|ˆƒS|ˆƒS)Nr)r?rr@)rirSrjrrrV¢sz BoolEncoder..EncodeFieldN)rNrrWrHÚWIRETYPE_VARINT)rrr rTrUrVr)rirRrSrjrÚ BoolEncoder…s   rlcsDt|tjƒ‰t‰t‰|r,‡‡‡fdd„}|S‡‡‡fdd„}|SdS)z&Returns an encoder for a string field.cs<x6|D].}|jdƒ}|ˆƒˆ|ˆ|ƒ|ƒ||ƒqWdS)Nzutf-8)r))r?rrOrÚencoded)rRr+ÚtagrrrU²s   z*StringEncoder..EncodeRepeatedFieldcs*|jdƒ}|ˆƒˆ|ˆ|ƒ|ƒ||ƒS)Nzutf-8)r))r?rrOrm)rRr+rnrrrVºs z"StringEncoder..EncodeFieldN)rNrrWrHr)rrr rUrVr)rRr+rnrÚ StringEncoderªs rocsDt|tjƒ‰t‰t‰|r,‡‡‡fdd„}|S‡‡‡fdd„}|SdS)z%Returns an encoder for a bytes field.cs2x,|D]$}|ˆƒˆ|ˆ|ƒ|ƒ||ƒqWdS)Nr)r?rrOr)rRr+rnrrrUÊs z)BytesEncoder..EncodeRepeatedFieldcs |ˆƒˆ|ˆ|ƒ|ƒ||ƒS)Nr)r?rrO)rRr+rnrrrVÑsz!BytesEncoder..EncodeFieldN)rNrrWrHr)rrr rUrVr)rRr+rnrÚ BytesEncoderÂs rpcsDt|tjƒ‰t|tjƒ‰|r.‡‡fdd„}|S‡‡fdd„}|SdS)z%Returns an encoder for a group field.cs.x(|D] }|ˆƒ|j||ƒ|ˆƒqWdS)N)Ú_InternalSerialize)r?rrOr)Úend_tagÚ start_tagrrrUßs  z)GroupEncoder..EncodeRepeatedFieldcs|ˆƒ|j||ƒ|ˆƒS)N)rq)r?rrO)rrrsrrrVæs z!GroupEncoder..EncodeFieldN)rNrÚWIRETYPE_START_GROUPÚWIRETYPE_END_GROUP)rrr rUrVr)rrrsrÚ GroupEncoderØs  rvcs<t|tjƒ‰t‰|r&‡‡fdd„}|S‡‡fdd„}|SdS)z'Returns an encoder for a message field.cs6x0|D](}|ˆƒˆ||jƒ|ƒ|j||ƒqWdS)N)r.rq)r?rrOr)rRrnrrrUôs z+MessageEncoder..EncodeRepeatedFieldcs$|ˆƒˆ||jƒ|ƒ|j||ƒS)N)r.rq)r?rrO)rRrnrrrVûsz#MessageEncoder..EncodeFieldN)rNrrWrH)rrr rUrVr)rRrnrÚMessageEncoderís rwcsRdjtdtjƒtdtjƒt|ƒtdtjƒgƒ‰tdtjƒ‰t‰‡‡‡fdd„}|S)zäEncoder for extensions of MessageSet. The message set message looks like this: message MessageSet { repeated group Item = 1 { required int32 type_id = 2; required string message = 3; } } rGrrrcs,|ˆƒˆ||jƒ|ƒ|j||ƒ|ˆƒS)N)r.rq)r?rrO)Ú end_bytesrRÚ start_bytesrrrVs z*MessageSetItemEncoder..EncodeField) rJrNrrtrkrLrWrurH)rrVr)rxrRryrÚMessageSetItemEncoders    rzcs&|j‰t|jddƒ‰‡‡fdd„}|S)zÅEncoder for extensions of MessageSet. Maps always have a wire format like this: message MapEntry { key_type key = 1; value_type value = 2; } repeated MapEntry map = N; FcsD|rt|jƒƒn|}x*|D]"}ˆj|||d�}ˆ|||ƒqWdS)N)r3r)ÚsortedÚkeysr4)r?rrOZ value_keysr3r5)Úencode_messager8rrrV5s zMapEncoder..EncodeField)r8rwr9)r:rVr)r}r8rÚ MapEncoder&s r~)DÚ__doc__Ú __author__r]r=Zgoogle.protobuf.internalrrarbrrrr"r$r(Z Int32SizerZ Int64SizerZ EnumSizerZ UInt32SizerZ UInt64SizerZ ZigZagEncodeZ SInt32SizerZ SInt64SizerZ Fixed32SizerZ SFixed32SizerZ FloatSizerZ Fixed64SizerZ SFixed64SizerZ DoubleSizerZ BoolSizerr,r-r/r0r2r;rCrFrHZ_EncodeSignedVarintrLrNrYrZr`rfrkZ Int32EncoderZ Int64EncoderZ EnumEncoderZ UInt32EncoderZ UInt64EncoderZ SInt32EncoderZ SInt64EncoderZWIRETYPE_FIXED32ZFixed32EncoderZWIRETYPE_FIXED64ZFixed64EncoderZSFixed32EncoderZSFixed64EncoderZ FloatEncoderZ DoubleEncoderrlrorprvrwrzr~rrrrÚAsn !   )"&R       %