Encode a Python value to TLV binary format. Args: value: Python value to encode (None, bool, int, float, bytes, str, list, or dict) Returns: bytes: TLV-encoded binary data Raises: DirtyProtocolError: If value
(value)
| 51 | |
| 52 | @staticmethod |
| 53 | def encode(value) -> bytes: class="cm"># pylint: disable=too-many-return-statements |
| 54 | class="st">""" |
| 55 | Encode a Python value to TLV binary format. |
| 56 | |
| 57 | Args: |
| 58 | value: Python value to encode (None, bool, int, float, |
| 59 | bytes, str, list, or dict) |
| 60 | |
| 61 | Returns: |
| 62 | bytes: TLV-encoded binary data |
| 63 | |
| 64 | Raises: |
| 65 | DirtyProtocolError: If value type is not supported |
| 66 | class="st">""" |
| 67 | if value is None: |
| 68 | return bytes([TYPE_NONE]) |
| 69 | |
| 70 | if isinstance(value, bool): |
| 71 | class="cm"># bool must come before int since bool is a subclass of int |
| 72 | return bytes([TYPE_BOOL, 0x01 if value else 0x00]) |
| 73 | |
| 74 | if isinstance(value, int): |
| 75 | return bytes([TYPE_INT64]) + struct.pack(class="st">">q", value) |
| 76 | |
| 77 | if isinstance(value, float): |
| 78 | return bytes([TYPE_FLOAT64]) + struct.pack(class="st">">d", value) |
| 79 | |
| 80 | if isinstance(value, bytes): |
| 81 | if len(value) > MAX_BYTES_SIZE: |
| 82 | raise DirtyProtocolError( |
| 83 | fclass="st">"Bytes too large: {len(value)} bytes " |
| 84 | fclass="st">"(max: {MAX_BYTES_SIZE})" |
| 85 | ) |
| 86 | return bytes([TYPE_BYTES]) + struct.pack(class="st">">I", len(value)) + value |
| 87 | |
| 88 | if isinstance(value, str): |
| 89 | encoded = value.encode(class="st">"utf-8") |
| 90 | if len(encoded) > MAX_STRING_SIZE: |
| 91 | raise DirtyProtocolError( |
| 92 | fclass="st">"String too large: {len(encoded)} bytes " |
| 93 | fclass="st">"(max: {MAX_STRING_SIZE})" |
| 94 | ) |
| 95 | return bytes([TYPE_STRING]) + struct.pack(class="st">">I", len(encoded)) + encoded |
| 96 | |
| 97 | if isinstance(value, (list, tuple)): |
| 98 | if len(value) > MAX_LIST_SIZE: |
| 99 | raise DirtyProtocolError( |
| 100 | fclass="st">"List too large: {len(value)} items " |
| 101 | fclass="st">"(max: {MAX_LIST_SIZE})" |
| 102 | ) |
| 103 | parts = [bytes([TYPE_LIST]), struct.pack(class="st">">I", len(value))] |
| 104 | for item in value: |
| 105 | parts.append(TLVEncoder.encode(item)) |
| 106 | return bclass="st">"".join(parts) |
| 107 | |
| 108 | if isinstance(value, dict): |
| 109 | if len(value) > MAX_DICT_SIZE: |
| 110 | raise DirtyProtocolError( |