def write_uvarint(w: Writer, n: int) -> None: ensure(0 <= n <= 0xFFFF_FFFF_FFFF_FFFF) shifted = 1 while shifted: shifted = n >> 7 byte = (n & 0x7F) | (0x80 if shifted else 0x00) w.append(byte) n = shifted
def write_uint64_be(w: Writer, n: int) -> int: ensure(0 <= n <= 0xFFFFFFFFFFFFFFFF) w.append((n >> 56) & 0xFF) w.append((n >> 48) & 0xFF) w.append((n >> 40) & 0xFF) w.append((n >> 32) & 0xFF) w.append((n >> 24) & 0xFF) w.append((n >> 16) & 0xFF) w.append((n >> 8) & 0xFF) w.append(n & 0xFF) return 8
def write_int(w: Writer, number: bytes) -> None: i = 0 while i < len(number) and number[i] == 0: i += 1 length = len(number) - i w.append(0x02) if length == 0 or number[i] >= 0x80: w.extend(encode_length(length + 1)) w.append(0x00) else: w.extend(encode_length(length)) w.extend(memoryview(number)[i:])
def write_varint(w: Writer, val: int) -> None: """ Implements variable-length int encoding from Ripple. See: https://ripple.com/wiki/Binary_Format#Variable_Length_Data_Encoding """ if val < 0: raise ValueError("Only non-negative integers are supported") elif val < 192: w.append(val) elif val <= 12480: val -= 193 w.append(193 + rshift(val, 8)) w.append(val & 0xFF) elif val <= 918744: val -= 12481 w.append(241 + rshift(val, 16)) w.append(rshift(val, 8) & 0xFF) w.append(val & 0xFF) else: raise ValueError("Value is too large")
def write_compact_size(w: Writer, n: int) -> None: ensure(0 <= n <= 0xFFFF_FFFF) if n < 253: w.append(n & 0xFF) elif n < 0x1_0000: w.append(253) write_uint16_le(w, n) elif n < 0x1_0000_0000: w.append(254) write_uint32_le(w, n) else: w.append(255) write_uint64_le(w, n)
def write_type(w: Writer, field: RippleField) -> None: if field.key <= 0xF: w.append((field.type << 4) | field.key) else: # this concerns two-bytes fields such as lastLedgerSequence w.append(field.type << 4) w.append(field.key)
def write_uint32_be(w: Writer, n: int) -> int: ensure(0 <= n <= 0xFFFFFFFF) w.append((n >> 24) & 0xFF) w.append((n >> 16) & 0xFF) w.append((n >> 8) & 0xFF) w.append(n & 0xFF) return 4
def write_header( w: Writer, length: int, header_byte: int, data_start: bytes | None = None, ) -> None: if length == 1 and data_start is not None and data_start[0] <= 0x7F: # no header when encoding one byte below 0x80 pass elif length <= 55: w.append(header_byte + length) else: encoded_length = int_to_bytes(length) w.append(header_byte + 55 + len(encoded_length)) w.extend(encoded_length)
def write(w: Writer, field: RippleField, value: int | bytes | str | None) -> None: if value is None: return write_type(w, field) if field.type == FIELD_TYPE_INT16: assert isinstance(value, int) w.extend(value.to_bytes(2, "big")) elif field.type == FIELD_TYPE_INT32: assert isinstance(value, int) w.extend(value.to_bytes(4, "big")) elif field.type == FIELD_TYPE_AMOUNT: assert isinstance(value, int) w.extend(serialize_amount(value)) elif field.type == FIELD_TYPE_ACCOUNT: assert isinstance(value, str) write_bytes_varint(w, helpers.decode_address(value)) elif field.type == FIELD_TYPE_VL: assert isinstance(value, (bytes, bytearray)) write_bytes_varint(w, value) else: raise ValueError("Unknown field type")
def write_bytes_reversed(w: Writer, b: bytes, length: int) -> int: ensure(len(b) == length) w.extend(bytes(reversed(b))) return length
def write_bytes_reversed(w: Writer, b: bytes) -> int: w.extend(bytes(reversed(b))) return len(b)
def write_bytes(w: Writer, b: bytes) -> int: w.extend(b) return len(b)
def write_uint16_le(w: Writer, n: int) -> int: ensure(0 <= n <= 0xFFFF) w.append(n & 0xFF) w.append((n >> 8) & 0xFF) return 2
def write_uint8(w: Writer, n: int) -> int: ensure(0 <= n <= 0xFF) w.append(n) return 1
def write_bytes_varint(w: Writer, value: bytes) -> None: """Serialize a variable length bytes.""" write_varint(w, len(value)) w.extend(value)
def write_bytes_fixed(w: Writer, b: bytes, length: int) -> int: ensure(len(b) == length) w.extend(b) return length
def write_bytes_unchecked(w: Writer, b: Union[bytes, memoryview]) -> int: w.extend(b) return len(b)
def write_bytes_unchecked(w: Writer, b: bytes) -> int: w.extend(b) return len(b)
def write_string(w: Writer, string: bytes) -> None: write_header(w, len(string), STRING_HEADER_BYTE, string) w.extend(string)
def write_bitcoin_varint(w: Writer, n: int) -> None: ensure(0 <= n <= 0xFFFF_FFFF) if n < 253: w.append(n & 0xFF) elif n < 0x1_0000: w.append(253) w.append(n & 0xFF) w.append((n >> 8) & 0xFF) else: w.append(254) w.append(n & 0xFF) w.append((n >> 8) & 0xFF) w.append((n >> 16) & 0xFF) w.append((n >> 24) & 0xFF)