rombob 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rombob/__init__.py +153 -0
- rombob/aliases.py +42 -0
- rombob/buffers.py +109 -0
- rombob/codecs.py +585 -0
- rombob/compiler.py +926 -0
- rombob/errors.py +2 -0
- rombob/factory.py +213 -0
- rombob/metadata.py +173 -0
- rombob/parser.py +408 -0
- rombob/tracing.py +127 -0
- rombob/typing.py +18 -0
- rombob-1.0.0.dist-info/METADATA +224 -0
- rombob-1.0.0.dist-info/RECORD +15 -0
- rombob-1.0.0.dist-info/WHEEL +4 -0
- rombob-1.0.0.dist-info/licenses/LICENSE +207 -0
rombob/__init__.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""rombob: binary serialization using type hints and annotations."""
|
|
2
|
+
|
|
3
|
+
from .aliases import F16_B as F16_B
|
|
4
|
+
from .aliases import F16_L as F16_L
|
|
5
|
+
from .aliases import F32_B as F32_B
|
|
6
|
+
from .aliases import F32_L as F32_L
|
|
7
|
+
from .aliases import F64_B as F64_B
|
|
8
|
+
from .aliases import F64_L as F64_L
|
|
9
|
+
from .aliases import I8_B as I8_B
|
|
10
|
+
from .aliases import I8_L as I8_L
|
|
11
|
+
from .aliases import I16_B as I16_B
|
|
12
|
+
from .aliases import I16_L as I16_L
|
|
13
|
+
from .aliases import I24_B as I24_B
|
|
14
|
+
from .aliases import I24_L as I24_L
|
|
15
|
+
from .aliases import I32_B as I32_B
|
|
16
|
+
from .aliases import I32_L as I32_L
|
|
17
|
+
from .aliases import I48_B as I48_B
|
|
18
|
+
from .aliases import I48_L as I48_L
|
|
19
|
+
from .aliases import I64_B as I64_B
|
|
20
|
+
from .aliases import I64_L as I64_L
|
|
21
|
+
from .aliases import U8_B as U8_B
|
|
22
|
+
from .aliases import U8_L as U8_L
|
|
23
|
+
from .aliases import U16_B as U16_B
|
|
24
|
+
from .aliases import U16_L as U16_L
|
|
25
|
+
from .aliases import U24_B as U24_B
|
|
26
|
+
from .aliases import U24_L as U24_L
|
|
27
|
+
from .aliases import U32_B as U32_B
|
|
28
|
+
from .aliases import U32_L as U32_L
|
|
29
|
+
from .aliases import U48_B as U48_B
|
|
30
|
+
from .aliases import U48_L as U48_L
|
|
31
|
+
from .aliases import U64_B as U64_B
|
|
32
|
+
from .aliases import U64_L as U64_L
|
|
33
|
+
from .aliases import IVInt as IVInt
|
|
34
|
+
from .aliases import Raw as Raw
|
|
35
|
+
from .aliases import UVInt as UVInt
|
|
36
|
+
from .buffers import Reader as Reader
|
|
37
|
+
from .buffers import Writer as Writer
|
|
38
|
+
from .codecs import BytesCodec as BytesCodec
|
|
39
|
+
from .codecs import Codec as Codec
|
|
40
|
+
from .codecs import CollectionCodec as CollectionCodec
|
|
41
|
+
from .codecs import EnumCodec as EnumCodec
|
|
42
|
+
from .codecs import IntCodec as IntCodec
|
|
43
|
+
from .codecs import LiteralCodec as LiteralCodec
|
|
44
|
+
from .codecs import NamedCodec as NamedCodec
|
|
45
|
+
from .codecs import OptionalCodec as OptionalCodec
|
|
46
|
+
from .codecs import RawCodec as RawCodec
|
|
47
|
+
from .codecs import RefLenCodec as RefLenCodec
|
|
48
|
+
from .codecs import StringCodec as StringCodec
|
|
49
|
+
from .codecs import StructCodec as StructCodec
|
|
50
|
+
from .codecs import ValidatorCodec as ValidatorCodec
|
|
51
|
+
from .codecs import VarIntCodec as VarIntCodec
|
|
52
|
+
from .compiler import ClassCodec as ClassCodec
|
|
53
|
+
from .compiler import DynamicSegment as DynamicSegment
|
|
54
|
+
from .compiler import OptionalSegment as OptionalSegment
|
|
55
|
+
from .compiler import StructSegment as StructSegment
|
|
56
|
+
from .errors import BytesOperationError as BytesOperationError
|
|
57
|
+
from .factory import Factory as Factory
|
|
58
|
+
from .factory import decode as decode
|
|
59
|
+
from .factory import encode as encode
|
|
60
|
+
from .metadata import Ge as Ge
|
|
61
|
+
from .metadata import Gt as Gt
|
|
62
|
+
from .metadata import Le as Le
|
|
63
|
+
from .metadata import Len as Len
|
|
64
|
+
from .metadata import Lt as Lt
|
|
65
|
+
from .metadata import Named as Named
|
|
66
|
+
from .metadata import Predicate as Predicate
|
|
67
|
+
from .metadata import Prefix as Prefix
|
|
68
|
+
from .metadata import Range as Range
|
|
69
|
+
from .metadata import Skip as Skip
|
|
70
|
+
from .metadata import When as When
|
|
71
|
+
from .parser import get_codec as get_codec
|
|
72
|
+
from .typing import BE as BE
|
|
73
|
+
from .typing import LE as LE
|
|
74
|
+
from .typing import Args as Args
|
|
75
|
+
from .typing import ByteOrder as ByteOrder
|
|
76
|
+
from .typing import ParserContext as ParserContext
|
|
77
|
+
|
|
78
|
+
__all__ = [
|
|
79
|
+
"Named",
|
|
80
|
+
"Skip",
|
|
81
|
+
"Len",
|
|
82
|
+
"Prefix",
|
|
83
|
+
"Gt",
|
|
84
|
+
"Ge",
|
|
85
|
+
"Lt",
|
|
86
|
+
"Le",
|
|
87
|
+
"Range",
|
|
88
|
+
"Predicate",
|
|
89
|
+
"When",
|
|
90
|
+
"RefLenCodec",
|
|
91
|
+
"BytesOperationError",
|
|
92
|
+
"Reader",
|
|
93
|
+
"Writer",
|
|
94
|
+
"ByteOrder",
|
|
95
|
+
"LE",
|
|
96
|
+
"BE",
|
|
97
|
+
"Codec",
|
|
98
|
+
"StructCodec",
|
|
99
|
+
"IntCodec",
|
|
100
|
+
"VarIntCodec",
|
|
101
|
+
"StringCodec",
|
|
102
|
+
"BytesCodec",
|
|
103
|
+
"CollectionCodec",
|
|
104
|
+
"RawCodec",
|
|
105
|
+
"OptionalCodec",
|
|
106
|
+
"ValidatorCodec",
|
|
107
|
+
"EnumCodec",
|
|
108
|
+
"Factory",
|
|
109
|
+
"LiteralCodec",
|
|
110
|
+
"NamedCodec",
|
|
111
|
+
"ClassCodec",
|
|
112
|
+
"StructSegment",
|
|
113
|
+
"DynamicSegment",
|
|
114
|
+
"OptionalSegment",
|
|
115
|
+
"I8_L",
|
|
116
|
+
"I8_B",
|
|
117
|
+
"U8_L",
|
|
118
|
+
"U8_B",
|
|
119
|
+
"I16_L",
|
|
120
|
+
"I16_B",
|
|
121
|
+
"U16_L",
|
|
122
|
+
"U16_B",
|
|
123
|
+
"I24_L",
|
|
124
|
+
"I24_B",
|
|
125
|
+
"U24_L",
|
|
126
|
+
"U24_B",
|
|
127
|
+
"I32_L",
|
|
128
|
+
"I32_B",
|
|
129
|
+
"U32_L",
|
|
130
|
+
"U32_B",
|
|
131
|
+
"I48_L",
|
|
132
|
+
"I48_B",
|
|
133
|
+
"U48_L",
|
|
134
|
+
"U48_B",
|
|
135
|
+
"I64_L",
|
|
136
|
+
"I64_B",
|
|
137
|
+
"U64_L",
|
|
138
|
+
"U64_B",
|
|
139
|
+
"F16_L",
|
|
140
|
+
"F16_B",
|
|
141
|
+
"F32_L",
|
|
142
|
+
"F32_B",
|
|
143
|
+
"F64_L",
|
|
144
|
+
"F64_B",
|
|
145
|
+
"IVInt",
|
|
146
|
+
"UVInt",
|
|
147
|
+
"Raw",
|
|
148
|
+
"ParserContext",
|
|
149
|
+
"Args",
|
|
150
|
+
"get_codec",
|
|
151
|
+
"encode",
|
|
152
|
+
"decode",
|
|
153
|
+
]
|
rombob/aliases.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Public `Annotated` aliases for the common binary types.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import typing as t
|
|
6
|
+
|
|
7
|
+
from .codecs import IntCodec, RawCodec, StructCodec, VarIntCodec
|
|
8
|
+
from .typing import BE, LE
|
|
9
|
+
|
|
10
|
+
I8_L = t.Annotated[int, StructCodec("<b")]
|
|
11
|
+
I8_B = t.Annotated[int, StructCodec(">b")]
|
|
12
|
+
U8_L = t.Annotated[int, StructCodec("<B")]
|
|
13
|
+
U8_B = t.Annotated[int, StructCodec(">B")]
|
|
14
|
+
I16_L = t.Annotated[int, StructCodec("<h")]
|
|
15
|
+
I16_B = t.Annotated[int, StructCodec(">h")]
|
|
16
|
+
U16_L = t.Annotated[int, StructCodec("<H")]
|
|
17
|
+
U16_B = t.Annotated[int, StructCodec(">H")]
|
|
18
|
+
I24_L = t.Annotated[int, IntCodec(length=3, byteorder=LE, signed=True)]
|
|
19
|
+
I24_B = t.Annotated[int, IntCodec(length=3, byteorder=BE, signed=True)]
|
|
20
|
+
U24_L = t.Annotated[int, IntCodec(length=3, byteorder=LE, signed=False)]
|
|
21
|
+
U24_B = t.Annotated[int, IntCodec(length=3, byteorder=BE, signed=False)]
|
|
22
|
+
I32_L = t.Annotated[int, StructCodec("<i")]
|
|
23
|
+
I32_B = t.Annotated[int, StructCodec(">i")]
|
|
24
|
+
U32_L = t.Annotated[int, StructCodec("<I")]
|
|
25
|
+
U32_B = t.Annotated[int, StructCodec(">I")]
|
|
26
|
+
I48_L = t.Annotated[int, IntCodec(length=6, byteorder=LE, signed=True)]
|
|
27
|
+
I48_B = t.Annotated[int, IntCodec(length=6, byteorder=BE, signed=True)]
|
|
28
|
+
U48_L = t.Annotated[int, IntCodec(length=6, byteorder=LE, signed=False)]
|
|
29
|
+
U48_B = t.Annotated[int, IntCodec(length=6, byteorder=BE, signed=False)]
|
|
30
|
+
I64_L = t.Annotated[int, StructCodec("<q")]
|
|
31
|
+
I64_B = t.Annotated[int, StructCodec(">q")]
|
|
32
|
+
U64_L = t.Annotated[int, StructCodec("<Q")]
|
|
33
|
+
U64_B = t.Annotated[int, StructCodec(">Q")]
|
|
34
|
+
F16_L = t.Annotated[float, StructCodec("<e")]
|
|
35
|
+
F16_B = t.Annotated[float, StructCodec(">e")]
|
|
36
|
+
F32_L = t.Annotated[float, StructCodec("<f")]
|
|
37
|
+
F32_B = t.Annotated[float, StructCodec(">f")]
|
|
38
|
+
F64_L = t.Annotated[float, StructCodec("<d")]
|
|
39
|
+
F64_B = t.Annotated[float, StructCodec(">d")]
|
|
40
|
+
IVInt = t.Annotated[int, VarIntCodec(signed=True)]
|
|
41
|
+
UVInt = t.Annotated[int, VarIntCodec(signed=False)]
|
|
42
|
+
Raw = t.Annotated[bytes, RawCodec()]
|
rombob/buffers.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import struct as s
|
|
2
|
+
import typing as t
|
|
3
|
+
|
|
4
|
+
from .errors import BytesOperationError
|
|
5
|
+
from .typing import Buffer
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Reader:
|
|
9
|
+
"""
|
|
10
|
+
Cursor over an input buffer.
|
|
11
|
+
|
|
12
|
+
The reader never slices-and-reassigns the buffer: the position is the
|
|
13
|
+
`offset` only. All values handed out by codecs are copies.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
__slots__ = ("view", "offset", "data")
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
data: Buffer,
|
|
21
|
+
offset: int = 0,
|
|
22
|
+
shared: dict[str, t.Any] | None = None,
|
|
23
|
+
) -> None:
|
|
24
|
+
view = memoryview(data)
|
|
25
|
+
if view.format != "B" or view.ndim != 1:
|
|
26
|
+
view = view.cast("B")
|
|
27
|
+
self.view = view
|
|
28
|
+
self.offset = offset
|
|
29
|
+
self.data: dict[str, t.Any] = {} if shared is None else shared
|
|
30
|
+
|
|
31
|
+
def __repr__(self) -> str:
|
|
32
|
+
return f"Reader(offset={self.offset}, size={len(self.view)})"
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def remaining(self) -> int:
|
|
36
|
+
return len(self.view) - self.offset
|
|
37
|
+
|
|
38
|
+
def take(self, n: int) -> memoryview:
|
|
39
|
+
"Return a view of the next n bytes and advance"
|
|
40
|
+
start = self.offset
|
|
41
|
+
end = start + n
|
|
42
|
+
if n < 0 or end > len(self.view):
|
|
43
|
+
raise BytesOperationError(
|
|
44
|
+
f"Not enough data: need {n} bytes at offset {start}, "
|
|
45
|
+
f"only {len(self.view) - start} left"
|
|
46
|
+
)
|
|
47
|
+
self.offset = end
|
|
48
|
+
return self.view[start:end]
|
|
49
|
+
|
|
50
|
+
def peek(self, n: int, skip: int = 0) -> memoryview:
|
|
51
|
+
"Return a view of n bytes starting `skip` bytes ahead, don't advance"
|
|
52
|
+
start = self.offset + skip
|
|
53
|
+
end = start + n
|
|
54
|
+
if n < 0 or skip < 0 or end > len(self.view):
|
|
55
|
+
raise BytesOperationError(
|
|
56
|
+
f"Not enough data: need {n} bytes at offset {start}, "
|
|
57
|
+
f"only {max(len(self.view) - start, 0)} left"
|
|
58
|
+
)
|
|
59
|
+
return self.view[start:end]
|
|
60
|
+
|
|
61
|
+
def rest(self) -> bytes:
|
|
62
|
+
"Copy of everything left; advances to the end"
|
|
63
|
+
rv = bytes(self.view[self.offset :])
|
|
64
|
+
self.offset = len(self.view)
|
|
65
|
+
return rv
|
|
66
|
+
|
|
67
|
+
def unpack(self, st: s.Struct) -> tuple:
|
|
68
|
+
rv = st.unpack_from(self.view, self.offset)
|
|
69
|
+
self.offset += st.size
|
|
70
|
+
return rv
|
|
71
|
+
|
|
72
|
+
def to_writer(self) -> "Writer":
|
|
73
|
+
return Writer(shared=self.data)
|
|
74
|
+
|
|
75
|
+
def release(self) -> None:
|
|
76
|
+
try:
|
|
77
|
+
self.view.release()
|
|
78
|
+
except BufferError:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Writer:
|
|
83
|
+
"Append-only output buffer. `buffer` is always a bytearray."
|
|
84
|
+
|
|
85
|
+
__slots__ = ("buffer", "data")
|
|
86
|
+
|
|
87
|
+
def __init__(
|
|
88
|
+
self,
|
|
89
|
+
buffer: bytearray | None = None,
|
|
90
|
+
shared: dict[str, t.Any] | None = None,
|
|
91
|
+
) -> None:
|
|
92
|
+
self.buffer = bytearray() if buffer is None else buffer
|
|
93
|
+
self.data: dict[str, t.Any] = {} if shared is None else shared
|
|
94
|
+
|
|
95
|
+
def __repr__(self) -> str:
|
|
96
|
+
return f"Writer(length={len(self.buffer)})"
|
|
97
|
+
|
|
98
|
+
def write(self, b: Buffer) -> None:
|
|
99
|
+
self.buffer += b
|
|
100
|
+
|
|
101
|
+
def pack(self, st: s.Struct, *values: t.Any) -> None:
|
|
102
|
+
self.buffer += st.pack(*values)
|
|
103
|
+
|
|
104
|
+
def getvalue(self) -> bytes:
|
|
105
|
+
return bytes(self.buffer)
|
|
106
|
+
|
|
107
|
+
def to_reader(self) -> Reader:
|
|
108
|
+
"Reader over a snapshot of the buffer, sharing `data`"
|
|
109
|
+
return Reader(bytes(self.buffer), shared=self.data)
|