55 lines
1.6 KiB
Python
55 lines
1.6 KiB
Python
"""Byte-wise cursor utilities for decoding binary ring payloads."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import struct
|
|
|
|
|
|
class ByteCursor:
|
|
"""Read primitive values from bytes while tracking offset."""
|
|
|
|
def __init__(self, payload: bytes) -> None:
|
|
"""Create cursor at start of payload."""
|
|
self.payload = payload
|
|
self.offset = 0
|
|
|
|
def read_u8(self) -> int:
|
|
"""Read unsigned 8-bit integer."""
|
|
value = struct.unpack_from("<B", self.payload, self.offset)[0]
|
|
self.offset += 1
|
|
return value
|
|
|
|
def read_u16(self) -> int:
|
|
"""Read unsigned 16-bit integer."""
|
|
value = struct.unpack_from("<H", self.payload, self.offset)[0]
|
|
self.offset += 2
|
|
return value
|
|
|
|
def read_u32(self) -> int:
|
|
"""Read unsigned 32-bit integer."""
|
|
value = struct.unpack_from("<I", self.payload, self.offset)[0]
|
|
self.offset += 4
|
|
return value
|
|
|
|
def read_u64(self) -> int:
|
|
"""Read unsigned 64-bit integer."""
|
|
value = struct.unpack_from("<Q", self.payload, self.offset)[0]
|
|
self.offset += 8
|
|
return value
|
|
|
|
def read_f32(self) -> float:
|
|
"""Read 32-bit float."""
|
|
value = struct.unpack_from("<f", self.payload, self.offset)[0]
|
|
self.offset += 4
|
|
return float(value)
|
|
|
|
def read_bytes(self, size: int) -> bytes:
|
|
"""Read raw byte slice of fixed size."""
|
|
data = self.payload[self.offset : self.offset + size]
|
|
self.offset += size
|
|
return data
|
|
|
|
def remaining_bytes(self) -> int:
|
|
"""Return unread byte count."""
|
|
return len(self.payload) - self.offset
|