# thrift.protocol

> A module of thrift's API.

Apache Thrift wire protocols in pure Mojo — serialization only, no RPC.

Two protocols are implemented, each as a *reader* over a borrowed
`Span[UInt8]` and a *writer* that appends to an owned `List[UInt8]`:

* `TCompactProtocolReader` / `TCompactProtocolWriter` — the variable-length
  encoding described in `doc/specs/thrift-compact-protocol.md`. This is what
  Apache Parquet uses for its footer and page headers.
* `TBinaryProtocolReader` / `TBinaryProtocolWriter` — the fixed-width
  big-endian encoding from `doc/specs/thrift-binary-protocol.md`, in both
  strict (versioned) and non-strict message framing.

Both conform to the `TProtocolReader` / `TProtocolWriter` traits, so
generated struct code can be written once and used with either.

Everything is bounds checked. A truncated buffer, a bad protocol id or
version, a negative length, a container whose declared element count cannot
possibly fit in the bytes that remain, or a nesting depth beyond
`MAX_SKIP_DEPTH` raises rather than reading out of bounds or allocating on a
size an attacker chose.

## Structs

### `TCompactProtocolReader`

```mojo
struct TCompactProtocolReader[origin: ImmOrigin]
```

Decodes TCompactProtocol from a borrowed byte span.

Implements: `Copyable`, `Movable`, `TProtocolReader`

Fields:

- `data: Span[UInt8, origin]`
- `pos: Int`

#### `__init__`

```mojo
def __init__(out self, data: Span[UInt8, origin])
```

```mojo
def __init__(out self, data: Span[UInt8, origin], pos: Int)
```

#### `offset`

```mojo
def offset(self) -> Int
```

#### `remaining`

```mojo
def remaining(self) -> Int
```

#### `read_message_begin`

```mojo
def read_message_begin(mut self) -> Tuple[String, Int8, Int32]
```

#### `read_message_end`

```mojo
def read_message_end(mut self)
```

#### `read_struct_begin`

```mojo
def read_struct_begin(mut self)
```

#### `read_struct_end`

```mojo
def read_struct_end(mut self)
```

#### `read_field_begin`

```mojo
def read_field_begin(mut self) -> Tuple[Int8, Int16]
```

#### `read_field_end`

```mojo
def read_field_end(mut self)
```

#### `read_map_begin`

```mojo
def read_map_begin(mut self) -> Tuple[Int8, Int8, Int]
```

#### `read_map_end`

```mojo
def read_map_end(mut self)
```

#### `read_list_begin`

```mojo
def read_list_begin(mut self) -> Tuple[Int8, Int]
```

#### `read_list_end`

```mojo
def read_list_end(mut self)
```

#### `read_set_begin`

```mojo
def read_set_begin(mut self) -> Tuple[Int8, Int]
```

#### `read_set_end`

```mojo
def read_set_end(mut self)
```

#### `read_bool`

```mojo
def read_bool(mut self) -> Bool
```

#### `read_byte`

```mojo
def read_byte(mut self) -> Int8
```

#### `read_i16`

```mojo
def read_i16(mut self) -> Int16
```

#### `read_i32`

```mojo
def read_i32(mut self) -> Int32
```

#### `read_i64`

```mojo
def read_i64(mut self) -> Int64
```

#### `read_double`

```mojo
def read_double(mut self) -> Float64
```

#### `read_binary`

```mojo
def read_binary(mut self) -> List[UInt8]
```

#### `read_binary_view`

```mojo
def read_binary_view(mut self) -> Span[UInt8, origin]
```

Zero-copy variant of `read_binary`, valid as long as the input is.

#### `read_string`

```mojo
def read_string(mut self) -> String
```

#### `read_uuid`

```mojo
def read_uuid(mut self) -> List[UInt8]
```

#### `skip`

```mojo
def skip(mut self, ttype: Int8)
```

### `TCompactProtocolWriter`

```mojo
struct TCompactProtocolWriter
```

Encodes TCompactProtocol into an owned byte list.

Implements: `Copyable`, `Defaultable`, `Movable`, `Sized`, `TProtocolWriter`

Fields:

- `out: List[UInt8]`

#### `__init__`

```mojo
def __init__(out self)
```

```mojo
def __init__(out self, capacity: Int)
```

#### `__len__`

```mojo
def __len__(self) -> Int
```

#### `take`

```mojo
def take(deinit self) -> List[UInt8]
```

#### `bytes`

```mojo
def bytes(self) -> List[UInt8]
```

#### `write_message_begin`

```mojo
def write_message_begin(mut self, name: StringSpan, mtype: Int8, seqid: Int32)
```

#### `write_message_end`

```mojo
def write_message_end(mut self)
```

#### `write_struct_begin`

```mojo
def write_struct_begin(mut self)
```

#### `write_struct_end`

```mojo
def write_struct_end(mut self)
```

#### `write_field_begin`

```mojo
def write_field_begin(mut self, ftype: Int8, fid: Int16)
```

#### `write_field_end`

```mojo
def write_field_end(mut self)
```

#### `write_field_stop`

```mojo
def write_field_stop(mut self)
```

#### `write_map_begin`

```mojo
def write_map_begin(mut self, ktype: Int8, vtype: Int8, size: Int)
```

#### `write_map_end`

```mojo
def write_map_end(mut self)
```

#### `write_list_begin`

```mojo
def write_list_begin(mut self, etype: Int8, size: Int)
```

#### `write_list_end`

```mojo
def write_list_end(mut self)
```

#### `write_set_begin`

```mojo
def write_set_begin(mut self, etype: Int8, size: Int)
```

#### `write_set_end`

```mojo
def write_set_end(mut self)
```

#### `write_bool`

```mojo
def write_bool(mut self, value: Bool)
```

#### `write_byte`

```mojo
def write_byte(mut self, value: Int8)
```

#### `write_i16`

```mojo
def write_i16(mut self, value: Int16)
```

#### `write_i32`

```mojo
def write_i32(mut self, value: Int32)
```

#### `write_i64`

```mojo
def write_i64(mut self, value: Int64)
```

#### `write_double`

```mojo
def write_double(mut self, value: Float64)
```

#### `write_binary`

```mojo
def write_binary(mut self, value: Span[UInt8])
```

#### `write_string`

```mojo
def write_string(mut self, value: StringSpan)
```

#### `write_uuid`

```mojo
def write_uuid(mut self, value: Span[UInt8])
```

### `TBinaryProtocolReader`

```mojo
struct TBinaryProtocolReader[origin: ImmOrigin]
```

Decodes TBinaryProtocol (strict or non-strict) from a byte span.

Implements: `Copyable`, `Movable`, `TProtocolReader`

Fields:

- `data: Span[UInt8, origin]`
- `pos: Int`
- `strict_read: Bool`

#### `__init__`

```mojo
def __init__(out self, data: Span[UInt8, origin])
```

```mojo
def __init__(out self, data: Span[UInt8, origin], *, strict_read: Bool)
```

#### `offset`

```mojo
def offset(self) -> Int
```

#### `remaining`

```mojo
def remaining(self) -> Int
```

#### `read_message_begin`

```mojo
def read_message_begin(mut self) -> Tuple[String, Int8, Int32]
```

#### `read_message_end`

```mojo
def read_message_end(mut self)
```

#### `read_struct_begin`

```mojo
def read_struct_begin(mut self)
```

#### `read_struct_end`

```mojo
def read_struct_end(mut self)
```

#### `read_field_begin`

```mojo
def read_field_begin(mut self) -> Tuple[Int8, Int16]
```

#### `read_field_end`

```mojo
def read_field_end(mut self)
```

#### `read_map_begin`

```mojo
def read_map_begin(mut self) -> Tuple[Int8, Int8, Int]
```

#### `read_map_end`

```mojo
def read_map_end(mut self)
```

#### `read_list_begin`

```mojo
def read_list_begin(mut self) -> Tuple[Int8, Int]
```

#### `read_list_end`

```mojo
def read_list_end(mut self)
```

#### `read_set_begin`

```mojo
def read_set_begin(mut self) -> Tuple[Int8, Int]
```

#### `read_set_end`

```mojo
def read_set_end(mut self)
```

#### `read_bool`

```mojo
def read_bool(mut self) -> Bool
```

#### `read_byte`

```mojo
def read_byte(mut self) -> Int8
```

#### `read_i16`

```mojo
def read_i16(mut self) -> Int16
```

#### `read_i32`

```mojo
def read_i32(mut self) -> Int32
```

#### `read_i64`

```mojo
def read_i64(mut self) -> Int64
```

#### `read_double`

```mojo
def read_double(mut self) -> Float64
```

#### `read_binary`

```mojo
def read_binary(mut self) -> List[UInt8]
```

#### `read_binary_view`

```mojo
def read_binary_view(mut self) -> Span[UInt8, origin]
```

#### `read_string`

```mojo
def read_string(mut self) -> String
```

#### `read_uuid`

```mojo
def read_uuid(mut self) -> List[UInt8]
```

#### `skip`

```mojo
def skip(mut self, ttype: Int8)
```

### `TBinaryProtocolWriter`

```mojo
struct TBinaryProtocolWriter
```

Encodes TBinaryProtocol into an owned byte list.

Implements: `Copyable`, `Defaultable`, `Movable`, `Sized`, `TProtocolWriter`

Fields:

- `out: List[UInt8]`
- `strict_write: Bool`

#### `__init__`

```mojo
def __init__(out self)
```

```mojo
def __init__(out self, *, strict_write: Bool)
```

#### `__len__`

```mojo
def __len__(self) -> Int
```

#### `take`

```mojo
def take(deinit self) -> List[UInt8]
```

#### `bytes`

```mojo
def bytes(self) -> List[UInt8]
```

#### `write_message_begin`

```mojo
def write_message_begin(mut self, name: StringSpan, mtype: Int8, seqid: Int32)
```

#### `write_message_end`

```mojo
def write_message_end(mut self)
```

#### `write_struct_begin`

```mojo
def write_struct_begin(mut self)
```

#### `write_struct_end`

```mojo
def write_struct_end(mut self)
```

#### `write_field_begin`

```mojo
def write_field_begin(mut self, ftype: Int8, fid: Int16)
```

#### `write_field_end`

```mojo
def write_field_end(mut self)
```

#### `write_field_stop`

```mojo
def write_field_stop(mut self)
```

#### `write_map_begin`

```mojo
def write_map_begin(mut self, ktype: Int8, vtype: Int8, size: Int)
```

#### `write_map_end`

```mojo
def write_map_end(mut self)
```

#### `write_list_begin`

```mojo
def write_list_begin(mut self, etype: Int8, size: Int)
```

#### `write_list_end`

```mojo
def write_list_end(mut self)
```

#### `write_set_begin`

```mojo
def write_set_begin(mut self, etype: Int8, size: Int)
```

#### `write_set_end`

```mojo
def write_set_end(mut self)
```

#### `write_bool`

```mojo
def write_bool(mut self, value: Bool)
```

#### `write_byte`

```mojo
def write_byte(mut self, value: Int8)
```

#### `write_i16`

```mojo
def write_i16(mut self, value: Int16)
```

#### `write_i32`

```mojo
def write_i32(mut self, value: Int32)
```

#### `write_i64`

```mojo
def write_i64(mut self, value: Int64)
```

#### `write_double`

```mojo
def write_double(mut self, value: Float64)
```

#### `write_binary`

```mojo
def write_binary(mut self, value: Span[UInt8])
```

#### `write_string`

```mojo
def write_string(mut self, value: StringSpan)
```

#### `write_uuid`

```mojo
def write_uuid(mut self, value: Span[UInt8])
```

## Traits

### `TProtocolReader`

```mojo
undefined
```

The read half of the Thrift protocol surface.

Generated struct readers are written against this trait, so the same
code decodes compact and binary streams.

#### `read_message_begin`

```mojo
def read_message_begin(mut self) -> Tuple[String, Int8, Int32]
```

#### `read_message_end`

```mojo
def read_message_end(mut self)
```

#### `read_struct_begin`

```mojo
def read_struct_begin(mut self)
```

#### `read_struct_end`

```mojo
def read_struct_end(mut self)
```

#### `read_field_begin`

```mojo
def read_field_begin(mut self) -> Tuple[Int8, Int16]
```

#### `read_field_end`

```mojo
def read_field_end(mut self)
```

#### `read_map_begin`

```mojo
def read_map_begin(mut self) -> Tuple[Int8, Int8, Int]
```

#### `read_map_end`

```mojo
def read_map_end(mut self)
```

#### `read_list_begin`

```mojo
def read_list_begin(mut self) -> Tuple[Int8, Int]
```

#### `read_list_end`

```mojo
def read_list_end(mut self)
```

#### `read_set_begin`

```mojo
def read_set_begin(mut self) -> Tuple[Int8, Int]
```

#### `read_set_end`

```mojo
def read_set_end(mut self)
```

#### `read_bool`

```mojo
def read_bool(mut self) -> Bool
```

#### `read_byte`

```mojo
def read_byte(mut self) -> Int8
```

#### `read_i16`

```mojo
def read_i16(mut self) -> Int16
```

#### `read_i32`

```mojo
def read_i32(mut self) -> Int32
```

#### `read_i64`

```mojo
def read_i64(mut self) -> Int64
```

#### `read_double`

```mojo
def read_double(mut self) -> Float64
```

#### `read_binary`

```mojo
def read_binary(mut self) -> List[UInt8]
```

#### `read_string`

```mojo
def read_string(mut self) -> String
```

#### `read_uuid`

```mojo
def read_uuid(mut self) -> List[UInt8]
```

#### `skip`

```mojo
def skip(mut self, ttype: Int8)
```

#### `offset`

```mojo
def offset(self) -> Int
```

#### `remaining`

```mojo
def remaining(self) -> Int
```

### `TProtocolWriter`

```mojo
undefined
```

The write half of the Thrift protocol surface.

#### `write_message_begin`

```mojo
def write_message_begin(mut self, name: StringSpan, mtype: Int8, seqid: Int32)
```

#### `write_message_end`

```mojo
def write_message_end(mut self)
```

#### `write_struct_begin`

```mojo
def write_struct_begin(mut self)
```

#### `write_struct_end`

```mojo
def write_struct_end(mut self)
```

#### `write_field_begin`

```mojo
def write_field_begin(mut self, ftype: Int8, fid: Int16)
```

#### `write_field_end`

```mojo
def write_field_end(mut self)
```

#### `write_field_stop`

```mojo
def write_field_stop(mut self)
```

#### `write_map_begin`

```mojo
def write_map_begin(mut self, ktype: Int8, vtype: Int8, size: Int)
```

#### `write_map_end`

```mojo
def write_map_end(mut self)
```

#### `write_list_begin`

```mojo
def write_list_begin(mut self, etype: Int8, size: Int)
```

#### `write_list_end`

```mojo
def write_list_end(mut self)
```

#### `write_set_begin`

```mojo
def write_set_begin(mut self, etype: Int8, size: Int)
```

#### `write_set_end`

```mojo
def write_set_end(mut self)
```

#### `write_bool`

```mojo
def write_bool(mut self, value: Bool)
```

#### `write_byte`

```mojo
def write_byte(mut self, value: Int8)
```

#### `write_i16`

```mojo
def write_i16(mut self, value: Int16)
```

#### `write_i32`

```mojo
def write_i32(mut self, value: Int32)
```

#### `write_i64`

```mojo
def write_i64(mut self, value: Int64)
```

#### `write_double`

```mojo
def write_double(mut self, value: Float64)
```

#### `write_binary`

```mojo
def write_binary(mut self, value: Span[UInt8])
```

#### `write_string`

```mojo
def write_string(mut self, value: StringSpan)
```

#### `write_uuid`

```mojo
def write_uuid(mut self, value: Span[UInt8])
```

## Functions

### `type_name`

```mojo
def type_name(t: Int8) -> String
```

A human name for a Thrift type id, for error messages.

### `zigzag_i32`

```mojo
def zigzag_i32(n: Int32) -> UInt64
```

`(n << 1) ^ (n >> 31)`, computed wide so it cannot overflow.

### `zigzag_i64`

```mojo
def zigzag_i64(n: Int64) -> UInt64
```

`(n << 1) ^ (n >> 63)` in the unsigned domain (Int64.MIN is fine).

### `unzigzag_i64`

```mojo
def unzigzag_i64(u: UInt64) -> Int64
```

The inverse of `zigzag_i64`.

### `unzigzag_i32`

```mojo
def unzigzag_i32(u: UInt64) -> Int32
```

The inverse of `zigzag_i32`, range-checked.

### `skip_value`

```mojo
def skip_value[P: TProtocolReader, //](mut p: P, ttype: Int8, depth: Int)
```

Consume one value of `ttype` without materialising it.

Forward compatibility depends on this: a reader that meets a field id it
does not know must still be able to step over the value, whatever shape
it has.

## Aliases

### `T_STOP`

```mojo
comptime T_STOP = Int8(0)
```

### `T_VOID`

```mojo
comptime T_VOID = Int8(1)
```

### `T_BOOL`

```mojo
comptime T_BOOL = Int8(2)
```

### `T_BYTE`

```mojo
comptime T_BYTE = Int8(3)
```

### `T_DOUBLE`

```mojo
comptime T_DOUBLE = Int8(4)
```

### `T_I16`

```mojo
comptime T_I16 = Int8(6)
```

### `T_I32`

```mojo
comptime T_I32 = Int8(8)
```

### `T_I64`

```mojo
comptime T_I64 = Int8(10)
```

### `T_STRING`

```mojo
comptime T_STRING = Int8(11)
```

### `T_STRUCT`

```mojo
comptime T_STRUCT = Int8(12)
```

### `T_MAP`

```mojo
comptime T_MAP = Int8(13)
```

### `T_SET`

```mojo
comptime T_SET = Int8(14)
```

### `T_LIST`

```mojo
comptime T_LIST = Int8(15)
```

### `T_UUID`

```mojo
comptime T_UUID = Int8(16)
```

### `T_I08`

```mojo
comptime T_I08 = T_BYTE
```

### `T_BINARY`

```mojo
comptime T_BINARY = T_STRING
```

### `COMPACT_PROTOCOL_ID`

```mojo
comptime COMPACT_PROTOCOL_ID = UInt8(130)
```

### `COMPACT_VERSION`

```mojo
comptime COMPACT_VERSION = UInt8(1)
```

### `COMPACT_VERSION_MASK`

```mojo
comptime COMPACT_VERSION_MASK = UInt8(31)
```

### `COMPACT_TYPE_MASK`

```mojo
comptime COMPACT_TYPE_MASK = UInt8(224)
```

### `COMPACT_TYPE_SHIFT_AMOUNT`

```mojo
comptime COMPACT_TYPE_SHIFT_AMOUNT = 5
```

### `C_STOP`

```mojo
comptime C_STOP = UInt8(0)
```

### `C_BOOLEAN_TRUE`

```mojo
comptime C_BOOLEAN_TRUE = UInt8(1)
```

### `C_BOOLEAN_FALSE`

```mojo
comptime C_BOOLEAN_FALSE = UInt8(2)
```

### `C_BYTE`

```mojo
comptime C_BYTE = UInt8(3)
```

### `C_I16`

```mojo
comptime C_I16 = UInt8(4)
```

### `C_I32`

```mojo
comptime C_I32 = UInt8(5)
```

### `C_I64`

```mojo
comptime C_I64 = UInt8(6)
```

### `C_DOUBLE`

```mojo
comptime C_DOUBLE = UInt8(7)
```

### `C_BINARY`

```mojo
comptime C_BINARY = UInt8(8)
```

### `C_LIST`

```mojo
comptime C_LIST = UInt8(9)
```

### `C_SET`

```mojo
comptime C_SET = UInt8(10)
```

### `C_MAP`

```mojo
comptime C_MAP = UInt8(11)
```

### `C_STRUCT`

```mojo
comptime C_STRUCT = UInt8(12)
```

### `C_UUID`

```mojo
comptime C_UUID = UInt8(13)
```

### `BINARY_VERSION_1`

```mojo
comptime BINARY_VERSION_1 = UInt32(2147549184)
```

### `BINARY_VERSION_MASK`

```mojo
comptime BINARY_VERSION_MASK = UInt32(4294901760)
```

### `MESSAGE_CALL`

```mojo
comptime MESSAGE_CALL = Int8(1)
```

### `MESSAGE_REPLY`

```mojo
comptime MESSAGE_REPLY = Int8(2)
```

### `MESSAGE_EXCEPTION`

```mojo
comptime MESSAGE_EXCEPTION = Int8(3)
```

### `MESSAGE_ONEWAY`

```mojo
comptime MESSAGE_ONEWAY = Int8(4)
```

### `MAX_SKIP_DEPTH`

```mojo
comptime MAX_SKIP_DEPTH = 64
```

### `MAX_VARINT_BYTES`

```mojo
comptime MAX_VARINT_BYTES = 10
```
