sltcodec 1.2.1__tar.gz → 1.3.0__tar.gz
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.
- {sltcodec-1.2.1 → sltcodec-1.3.0}/PKG-INFO +53 -36
- {sltcodec-1.2.1 → sltcodec-1.3.0}/README.md +52 -35
- {sltcodec-1.2.1 → sltcodec-1.3.0}/pyproject.toml +1 -1
- sltcodec-1.3.0/src/sltcodec/__init__.py +21 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/src/sltcodec/codec.py +104 -75
- {sltcodec-1.2.1 → sltcodec-1.3.0}/src/sltcodec/types.py +93 -11
- {sltcodec-1.2.1 → sltcodec-1.3.0}/tests/test_codec.py +17 -18
- {sltcodec-1.2.1 → sltcodec-1.3.0}/uv.lock +1 -1
- sltcodec-1.2.1/src/sltcodec/__init__.py +0 -20
- {sltcodec-1.2.1 → sltcodec-1.3.0}/.github/workflows/publish_to_pypi.yml +0 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/.github/workflows/publish_to_testpypi.yml +0 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/.gitignore +0 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/.python-version +0 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/.vscode/launch.json +0 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/.vscode/settings.json +0 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/LICENSE +0 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/bump_major.ps1 +0 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/bump_minor.ps1 +0 -0
- {sltcodec-1.2.1 → sltcodec-1.3.0}/bump_patch.ps1 +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sltcodec
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Decode and encode bytearrays according to struct layout definitions using sltcore.
|
|
5
5
|
Project-URL: Homepage, https://github.com/fangface-hub/StructLayoutToolkitCodec
|
|
6
6
|
Project-URL: Documentation, https://readthedocs.org
|
|
@@ -199,10 +199,10 @@ print(encoded_int, decoded_int)
|
|
|
199
199
|
print(encoded_float, decoded_float)
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
-
## Saving And Loading
|
|
202
|
+
## Saving And Loading Type Dictionaries
|
|
203
203
|
|
|
204
|
-
You can persist reusable structure definitions
|
|
205
|
-
`
|
|
204
|
+
You can persist reusable structure and enum definitions together via
|
|
205
|
+
`TypeDict` with `save_type_dict` / `load_type_dict`.
|
|
206
206
|
|
|
207
207
|
`InfoSize` values in `offset` and `size` are saved as typed dictionaries in
|
|
208
208
|
JSON. Expression-based offsets and sizes remain strings and are resolved when
|
|
@@ -212,25 +212,31 @@ the definition is used.
|
|
|
212
212
|
from pathlib import Path
|
|
213
213
|
|
|
214
214
|
from sltcore import InfoSize
|
|
215
|
-
from sltcodec import FieldDef, StructDef,
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
215
|
+
from sltcodec import EnumDef, FieldDef, StructDef, TypeDict, load_type_dict, save_type_dict
|
|
216
|
+
|
|
217
|
+
type_dict = TypeDict(
|
|
218
|
+
struct_dict={
|
|
219
|
+
"Header": StructDef(
|
|
220
|
+
name="Header",
|
|
221
|
+
description="Simple header",
|
|
222
|
+
fields=[
|
|
223
|
+
FieldDef(name="kind", offset=InfoSize(0, 0), size=InfoSize(1, 0), type="unsigned int"),
|
|
224
|
+
FieldDef(name="flags", offset=InfoSize(1, 0), size=InfoSize(1, 0), type="unsigned int"),
|
|
225
|
+
],
|
|
226
|
+
)
|
|
227
|
+
},
|
|
228
|
+
enum_dict={
|
|
229
|
+
"Status": EnumDef(name="Status", values={"OK": 0, "NG": 1}),
|
|
230
|
+
}
|
|
231
|
+
)
|
|
227
232
|
|
|
228
233
|
path = Path("struct_defs.json")
|
|
229
|
-
|
|
230
|
-
loaded =
|
|
234
|
+
save_type_dict(path, type_dict)
|
|
235
|
+
loaded = load_type_dict(path)
|
|
231
236
|
|
|
232
|
-
print(loaded["Header"].name)
|
|
233
|
-
print(loaded["Header"].description)
|
|
237
|
+
print(loaded.struct_dict["Header"].name)
|
|
238
|
+
print(loaded.struct_dict["Header"].description)
|
|
239
|
+
print(loaded.enum_dict["Status"].values["NG"])
|
|
234
240
|
```
|
|
235
241
|
|
|
236
242
|
Example output:
|
|
@@ -238,31 +244,42 @@ Example output:
|
|
|
238
244
|
```python
|
|
239
245
|
Header
|
|
240
246
|
Simple header
|
|
247
|
+
1
|
|
241
248
|
```
|
|
242
249
|
|
|
243
250
|
## Enum Definitions
|
|
244
251
|
|
|
245
252
|
`FieldDef.enum_def_name` holds only the name of an `EnumDef`, not the definition
|
|
246
|
-
itself.
|
|
247
|
-
`
|
|
248
|
-
|
|
253
|
+
itself. In practice, `TypeDict` is most useful when you pass both
|
|
254
|
+
`type_dict.struct_dict` and `type_dict.enum_dict` together: one resolves named
|
|
255
|
+
layout types and the other resolves enum labels. The example below uses both in
|
|
256
|
+
one decode flow.
|
|
249
257
|
|
|
250
258
|
```python
|
|
251
259
|
from sltcore import InfoSize
|
|
252
|
-
from sltcodec import EnumDef, FieldDef, decode
|
|
260
|
+
from sltcodec import EnumDef, EnumDict, FieldDef, StructDef, StructDict, TypeDict, decode
|
|
261
|
+
|
|
262
|
+
enum_dict = EnumDict({"Status": EnumDef(name="Status", values={"OK": 0, "NG": 1})})
|
|
263
|
+
|
|
264
|
+
packet_struct = StructDef(
|
|
265
|
+
name="Packet",
|
|
266
|
+
fields=[
|
|
267
|
+
FieldDef(name="status",
|
|
268
|
+
offset=InfoSize(0, 0),
|
|
269
|
+
size=InfoSize(1, 0),
|
|
270
|
+
type="unsigned int",
|
|
271
|
+
enum_def_name="Status"),
|
|
272
|
+
],
|
|
273
|
+
)
|
|
253
274
|
|
|
254
|
-
|
|
275
|
+
struct_dict = StructDict({"Packet": packet_struct})
|
|
255
276
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
offset=InfoSize(0, 0),
|
|
259
|
-
size=InfoSize(1, 0),
|
|
260
|
-
type="unsigned int",
|
|
261
|
-
enum_def_name="Status"),
|
|
262
|
-
]
|
|
277
|
+
type_dict = TypeDict(struct_dict=struct_dict.items_dict(),
|
|
278
|
+
enum_dict=enum_dict.items_dict())
|
|
263
279
|
|
|
264
|
-
decoded = decode(
|
|
265
|
-
|
|
280
|
+
decoded = decode(type_dict.struct_dict["Packet"],
|
|
281
|
+
bytearray(b"\x01"),
|
|
282
|
+
type_dict=type_dict)
|
|
266
283
|
|
|
267
284
|
print(decoded.field_instances[0].value)
|
|
268
285
|
print(decoded.field_instances[0].enum_item)
|
|
@@ -275,8 +292,8 @@ Output:
|
|
|
275
292
|
('NG', 1)
|
|
276
293
|
```
|
|
277
294
|
|
|
278
|
-
You can also persist enum definitions by name
|
|
279
|
-
`
|
|
295
|
+
You can also persist enum definitions by name through `TypeDict` using
|
|
296
|
+
`save_type_dict` / `load_type_dict`.
|
|
280
297
|
|
|
281
298
|
## Development
|
|
282
299
|
|
|
@@ -182,10 +182,10 @@ print(encoded_int, decoded_int)
|
|
|
182
182
|
print(encoded_float, decoded_float)
|
|
183
183
|
```
|
|
184
184
|
|
|
185
|
-
## Saving And Loading
|
|
185
|
+
## Saving And Loading Type Dictionaries
|
|
186
186
|
|
|
187
|
-
You can persist reusable structure definitions
|
|
188
|
-
`
|
|
187
|
+
You can persist reusable structure and enum definitions together via
|
|
188
|
+
`TypeDict` with `save_type_dict` / `load_type_dict`.
|
|
189
189
|
|
|
190
190
|
`InfoSize` values in `offset` and `size` are saved as typed dictionaries in
|
|
191
191
|
JSON. Expression-based offsets and sizes remain strings and are resolved when
|
|
@@ -195,25 +195,31 @@ the definition is used.
|
|
|
195
195
|
from pathlib import Path
|
|
196
196
|
|
|
197
197
|
from sltcore import InfoSize
|
|
198
|
-
from sltcodec import FieldDef, StructDef,
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
198
|
+
from sltcodec import EnumDef, FieldDef, StructDef, TypeDict, load_type_dict, save_type_dict
|
|
199
|
+
|
|
200
|
+
type_dict = TypeDict(
|
|
201
|
+
struct_dict={
|
|
202
|
+
"Header": StructDef(
|
|
203
|
+
name="Header",
|
|
204
|
+
description="Simple header",
|
|
205
|
+
fields=[
|
|
206
|
+
FieldDef(name="kind", offset=InfoSize(0, 0), size=InfoSize(1, 0), type="unsigned int"),
|
|
207
|
+
FieldDef(name="flags", offset=InfoSize(1, 0), size=InfoSize(1, 0), type="unsigned int"),
|
|
208
|
+
],
|
|
209
|
+
)
|
|
210
|
+
},
|
|
211
|
+
enum_dict={
|
|
212
|
+
"Status": EnumDef(name="Status", values={"OK": 0, "NG": 1}),
|
|
213
|
+
}
|
|
214
|
+
)
|
|
210
215
|
|
|
211
216
|
path = Path("struct_defs.json")
|
|
212
|
-
|
|
213
|
-
loaded =
|
|
217
|
+
save_type_dict(path, type_dict)
|
|
218
|
+
loaded = load_type_dict(path)
|
|
214
219
|
|
|
215
|
-
print(loaded["Header"].name)
|
|
216
|
-
print(loaded["Header"].description)
|
|
220
|
+
print(loaded.struct_dict["Header"].name)
|
|
221
|
+
print(loaded.struct_dict["Header"].description)
|
|
222
|
+
print(loaded.enum_dict["Status"].values["NG"])
|
|
217
223
|
```
|
|
218
224
|
|
|
219
225
|
Example output:
|
|
@@ -221,31 +227,42 @@ Example output:
|
|
|
221
227
|
```python
|
|
222
228
|
Header
|
|
223
229
|
Simple header
|
|
230
|
+
1
|
|
224
231
|
```
|
|
225
232
|
|
|
226
233
|
## Enum Definitions
|
|
227
234
|
|
|
228
235
|
`FieldDef.enum_def_name` holds only the name of an `EnumDef`, not the definition
|
|
229
|
-
itself.
|
|
230
|
-
`
|
|
231
|
-
|
|
236
|
+
itself. In practice, `TypeDict` is most useful when you pass both
|
|
237
|
+
`type_dict.struct_dict` and `type_dict.enum_dict` together: one resolves named
|
|
238
|
+
layout types and the other resolves enum labels. The example below uses both in
|
|
239
|
+
one decode flow.
|
|
232
240
|
|
|
233
241
|
```python
|
|
234
242
|
from sltcore import InfoSize
|
|
235
|
-
from sltcodec import EnumDef, FieldDef, decode
|
|
243
|
+
from sltcodec import EnumDef, EnumDict, FieldDef, StructDef, StructDict, TypeDict, decode
|
|
244
|
+
|
|
245
|
+
enum_dict = EnumDict({"Status": EnumDef(name="Status", values={"OK": 0, "NG": 1})})
|
|
246
|
+
|
|
247
|
+
packet_struct = StructDef(
|
|
248
|
+
name="Packet",
|
|
249
|
+
fields=[
|
|
250
|
+
FieldDef(name="status",
|
|
251
|
+
offset=InfoSize(0, 0),
|
|
252
|
+
size=InfoSize(1, 0),
|
|
253
|
+
type="unsigned int",
|
|
254
|
+
enum_def_name="Status"),
|
|
255
|
+
],
|
|
256
|
+
)
|
|
236
257
|
|
|
237
|
-
|
|
258
|
+
struct_dict = StructDict({"Packet": packet_struct})
|
|
238
259
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
offset=InfoSize(0, 0),
|
|
242
|
-
size=InfoSize(1, 0),
|
|
243
|
-
type="unsigned int",
|
|
244
|
-
enum_def_name="Status"),
|
|
245
|
-
]
|
|
260
|
+
type_dict = TypeDict(struct_dict=struct_dict.items_dict(),
|
|
261
|
+
enum_dict=enum_dict.items_dict())
|
|
246
262
|
|
|
247
|
-
decoded = decode(
|
|
248
|
-
|
|
263
|
+
decoded = decode(type_dict.struct_dict["Packet"],
|
|
264
|
+
bytearray(b"\x01"),
|
|
265
|
+
type_dict=type_dict)
|
|
249
266
|
|
|
250
267
|
print(decoded.field_instances[0].value)
|
|
251
268
|
print(decoded.field_instances[0].enum_item)
|
|
@@ -258,8 +275,8 @@ Output:
|
|
|
258
275
|
('NG', 1)
|
|
259
276
|
```
|
|
260
277
|
|
|
261
|
-
You can also persist enum definitions by name
|
|
262
|
-
`
|
|
278
|
+
You can also persist enum definitions by name through `TypeDict` using
|
|
279
|
+
`save_type_dict` / `load_type_dict`.
|
|
263
280
|
|
|
264
281
|
## Development
|
|
265
282
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .codec import (PRIMITIVE_TYPES, decode, encode, encode_field,
|
|
2
|
+
load_type_dict, save_type_dict)
|
|
3
|
+
from .types import (EnumDef, EnumDict, FieldDef, FieldInstance, StructDef,
|
|
4
|
+
StructDict, StructInstance, TypeDict)
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"PRIMITIVE_TYPES",
|
|
8
|
+
"EnumDef",
|
|
9
|
+
"EnumDict",
|
|
10
|
+
"FieldDef",
|
|
11
|
+
"FieldInstance",
|
|
12
|
+
"StructDef",
|
|
13
|
+
"StructDict",
|
|
14
|
+
"StructInstance",
|
|
15
|
+
"TypeDict",
|
|
16
|
+
"decode",
|
|
17
|
+
"encode",
|
|
18
|
+
"encode_field",
|
|
19
|
+
"load_type_dict",
|
|
20
|
+
"save_type_dict",
|
|
21
|
+
]
|
|
@@ -8,7 +8,8 @@ from typing import Any
|
|
|
8
8
|
from sltcalc import SltEval
|
|
9
9
|
from sltcore import Info, InfoSize, bits_get, bits_set
|
|
10
10
|
|
|
11
|
-
from .types import EnumDef, FieldDef, FieldInstance, StructDef, StructInstance
|
|
11
|
+
from .types import (EnumDef, FieldDef, FieldInstance, StructDef, StructInstance,
|
|
12
|
+
TypeDict)
|
|
12
13
|
|
|
13
14
|
PRIMITIVE_TYPES = {
|
|
14
15
|
"bool",
|
|
@@ -46,44 +47,78 @@ def _validate_struct_instance(struct_instance: StructInstance) -> None:
|
|
|
46
47
|
f"{type(field_instance).__name__}")
|
|
47
48
|
|
|
48
49
|
|
|
49
|
-
def
|
|
50
|
-
|
|
51
|
-
"""Save a structure definition dictionary to a JSON file."""
|
|
50
|
+
def save_type_dict(path: str | Path, type_dict: TypeDict) -> None:
|
|
51
|
+
"""Save TypeDict to a JSON file."""
|
|
52
52
|
payload = {
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
"struct_dict": {
|
|
54
|
+
name: struct_def.to_dict()
|
|
55
|
+
for name, struct_def in type_dict.struct_dict.items()
|
|
56
|
+
},
|
|
57
|
+
"enum_dict": {
|
|
58
|
+
name: enum_def.to_dict()
|
|
59
|
+
for name, enum_def in type_dict.enum_dict.items()
|
|
60
|
+
},
|
|
55
61
|
}
|
|
56
62
|
Path(path).write_text(json.dumps(payload, ensure_ascii=False, indent=2),
|
|
57
63
|
encoding="utf-8")
|
|
58
64
|
|
|
59
65
|
|
|
66
|
+
def load_type_dict(path: str | Path) -> TypeDict:
|
|
67
|
+
"""Load TypeDict from a JSON file."""
|
|
68
|
+
data = json.loads(Path(path).read_text(encoding="utf-8"))
|
|
69
|
+
|
|
70
|
+
struct_payload = data.get("struct_dict")
|
|
71
|
+
enum_payload = data.get("enum_dict")
|
|
72
|
+
|
|
73
|
+
if isinstance(struct_payload, dict) and isinstance(enum_payload, dict):
|
|
74
|
+
return TypeDict(
|
|
75
|
+
struct_dict={
|
|
76
|
+
name: StructDef.from_dict(struct_def_data)
|
|
77
|
+
for name, struct_def_data in struct_payload.items()
|
|
78
|
+
},
|
|
79
|
+
enum_dict={
|
|
80
|
+
name: EnumDef.from_dict(enum_def_data)
|
|
81
|
+
for name, enum_def_data in enum_payload.items()
|
|
82
|
+
},
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Backward compatibility: old files that stored only struct or enum maps.
|
|
86
|
+
legacy_entries: dict[str, Any] = data if isinstance(data, dict) else {}
|
|
87
|
+
if any(
|
|
88
|
+
isinstance(item, dict) and "fields" in item
|
|
89
|
+
for item in legacy_entries.values()):
|
|
90
|
+
return TypeDict(
|
|
91
|
+
struct_dict={
|
|
92
|
+
name: StructDef.from_dict(struct_def_data)
|
|
93
|
+
for name, struct_def_data in legacy_entries.items()
|
|
94
|
+
})
|
|
95
|
+
return TypeDict(
|
|
96
|
+
enum_dict={
|
|
97
|
+
name: EnumDef.from_dict(enum_def_data)
|
|
98
|
+
for name, enum_def_data in legacy_entries.items()
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def save_struct_def_dict(path: str | Path,
|
|
103
|
+
struct_def_dict: dict[str, StructDef]) -> None:
|
|
104
|
+
"""Save a structure definition dictionary to a JSON file."""
|
|
105
|
+
save_type_dict(path, TypeDict(struct_dict=struct_def_dict))
|
|
106
|
+
|
|
107
|
+
|
|
60
108
|
def load_struct_def_dict(path: str | Path) -> dict[str, StructDef]:
|
|
61
109
|
"""Load a structure definition dictionary from a JSON file."""
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
name: StructDef.from_dict(field_def_data)
|
|
65
|
-
for name, field_def_data in data.items()
|
|
66
|
-
}
|
|
110
|
+
return load_type_dict(path).struct_dict.items_dict()
|
|
67
111
|
|
|
68
112
|
|
|
69
113
|
def save_enum_def_dict(path: str | Path, enum_def_dict: dict[str,
|
|
70
114
|
EnumDef]) -> None:
|
|
71
115
|
"""Save an enum definition dictionary to a JSON file."""
|
|
72
|
-
|
|
73
|
-
name: enum_def.to_dict()
|
|
74
|
-
for name, enum_def in enum_def_dict.items()
|
|
75
|
-
}
|
|
76
|
-
Path(path).write_text(json.dumps(payload, ensure_ascii=False, indent=2),
|
|
77
|
-
encoding="utf-8")
|
|
116
|
+
save_type_dict(path, TypeDict(enum_dict=enum_def_dict))
|
|
78
117
|
|
|
79
118
|
|
|
80
119
|
def load_enum_def_dict(path: str | Path) -> dict[str, EnumDef]:
|
|
81
120
|
"""Load an enum definition dictionary from a JSON file."""
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
name: EnumDef.from_dict(enum_def_data)
|
|
85
|
-
for name, enum_def_data in data.items()
|
|
86
|
-
}
|
|
121
|
+
return load_type_dict(path).enum_dict.items_dict()
|
|
87
122
|
|
|
88
123
|
|
|
89
124
|
def _resolve_info_size(value: InfoSize | str, env: dict[str, Any]) -> InfoSize:
|
|
@@ -144,7 +179,7 @@ def _validate_padding_alignment_bits(padding_alignment_bits: int) -> None:
|
|
|
144
179
|
|
|
145
180
|
|
|
146
181
|
def _resolve_field_type(field_type: str | StructDef,
|
|
147
|
-
|
|
182
|
+
type_dict: TypeDict | None = None,
|
|
148
183
|
env: dict[str, Any] | None = None) -> str | StructDef:
|
|
149
184
|
"""Resolve a field type that can be primitive, named, or nested."""
|
|
150
185
|
if isinstance(field_type, StructDef):
|
|
@@ -152,7 +187,7 @@ def _resolve_field_type(field_type: str | StructDef,
|
|
|
152
187
|
if field_type in _PRIMITIVE_TYPES:
|
|
153
188
|
return field_type
|
|
154
189
|
|
|
155
|
-
resolved_struct_def = _get_struct_def(field_type,
|
|
190
|
+
resolved_struct_def = _get_struct_def(field_type, type_dict, env)
|
|
156
191
|
if isinstance(resolved_struct_def, StructDef):
|
|
157
192
|
return resolved_struct_def
|
|
158
193
|
if (isinstance(resolved_struct_def, str)
|
|
@@ -188,8 +223,7 @@ def _prepare_field_info(
|
|
|
188
223
|
field_def: FieldDef,
|
|
189
224
|
value: Any,
|
|
190
225
|
env: dict[str, Any],
|
|
191
|
-
|
|
192
|
-
enum_def_dict: dict[str, EnumDef] | None = None,
|
|
226
|
+
type_dict: TypeDict | None = None,
|
|
193
227
|
padding_alignment_bits: int = _DEFAULT_PADDING_ALIGNMENT_BITS,
|
|
194
228
|
) -> tuple[InfoSize, InfoSize, Info] | None:
|
|
195
229
|
"""Resolve a field definition into an offset, size, and info payload."""
|
|
@@ -198,7 +232,7 @@ def _prepare_field_info(
|
|
|
198
232
|
if size.byte == 0 and size.bit == 0:
|
|
199
233
|
return None
|
|
200
234
|
|
|
201
|
-
resolved_type = _resolve_field_type(field_def.type,
|
|
235
|
+
resolved_type = _resolve_field_type(field_def.type, type_dict, env)
|
|
202
236
|
if isinstance(resolved_type, StructDef):
|
|
203
237
|
if not isinstance(value, StructInstance):
|
|
204
238
|
raise TypeError(
|
|
@@ -206,8 +240,7 @@ def _prepare_field_info(
|
|
|
206
240
|
"values")
|
|
207
241
|
nested_bytes = encode(value,
|
|
208
242
|
bytearray(),
|
|
209
|
-
|
|
210
|
-
enum_def_dict,
|
|
243
|
+
type_dict,
|
|
211
244
|
padding_alignment_bits=padding_alignment_bits)
|
|
212
245
|
info = Info.from_bytes(bytes(nested_bytes), size, scale=field_def.scale)
|
|
213
246
|
else:
|
|
@@ -233,16 +266,15 @@ def encode_field(
|
|
|
233
266
|
value: Any,
|
|
234
267
|
buf: bytearray,
|
|
235
268
|
env: dict[str, Any] | None = None,
|
|
236
|
-
|
|
237
|
-
enum_def_dict: dict[str, EnumDef] | None = None,
|
|
269
|
+
type_dict: TypeDict | None = None,
|
|
238
270
|
padding_alignment_bits: int = _DEFAULT_PADDING_ALIGNMENT_BITS,
|
|
239
271
|
) -> None:
|
|
240
272
|
"""Encode a single field into a bytearray."""
|
|
241
273
|
if env is None:
|
|
242
274
|
env = {}
|
|
243
275
|
|
|
244
|
-
prepared = _prepare_field_info(field_def, value, env,
|
|
245
|
-
|
|
276
|
+
prepared = _prepare_field_info(field_def, value, env, type_dict,
|
|
277
|
+
padding_alignment_bits)
|
|
246
278
|
if prepared is None:
|
|
247
279
|
return
|
|
248
280
|
|
|
@@ -259,8 +291,7 @@ def encode_field(
|
|
|
259
291
|
def encode(
|
|
260
292
|
struct_instance: StructInstance,
|
|
261
293
|
buf: bytearray,
|
|
262
|
-
|
|
263
|
-
enum_def_dict: dict[str, EnumDef] | None = None,
|
|
294
|
+
type_dict: TypeDict | None = None,
|
|
264
295
|
padding_alignment_bits: int = _DEFAULT_PADDING_ALIGNMENT_BITS,
|
|
265
296
|
) -> bytearray:
|
|
266
297
|
"""Encode decode() result into a bytearray.
|
|
@@ -271,10 +302,9 @@ def encode(
|
|
|
271
302
|
The structure instance to encode.
|
|
272
303
|
buf : bytearray
|
|
273
304
|
The base bytearray instance to write into.
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
A dictionary of enum definitions, by default None.
|
|
305
|
+
type_dict : TypeDict | None, optional
|
|
306
|
+
Type dictionaries including structure and enum definitions,
|
|
307
|
+
by default None.
|
|
278
308
|
padding_alignment_bits : int, optional
|
|
279
309
|
The padding alignment boundary in bits, by default 32.
|
|
280
310
|
|
|
@@ -304,8 +334,7 @@ def encode(
|
|
|
304
334
|
for i in range(field_def.repeat):
|
|
305
335
|
field_def_repeat = _split_repeated_field(
|
|
306
336
|
field_def, i, env, current_offset)
|
|
307
|
-
encode_field(field_def_repeat, values[i], buf, env,
|
|
308
|
-
struct_def_dict, enum_def_dict,
|
|
337
|
+
encode_field(field_def_repeat, values[i], buf, env, type_dict,
|
|
309
338
|
padding_alignment_bits)
|
|
310
339
|
env[field_def_repeat.name] = values[i]
|
|
311
340
|
if isinstance(current_offset, InfoSize) and isinstance(
|
|
@@ -313,7 +342,7 @@ def encode(
|
|
|
313
342
|
current_offset += resolved_size
|
|
314
343
|
continue
|
|
315
344
|
|
|
316
|
-
encode_field(field_def, value, buf, env,
|
|
345
|
+
encode_field(field_def, value, buf, env, type_dict,
|
|
317
346
|
padding_alignment_bits)
|
|
318
347
|
env[field_def.name] = value
|
|
319
348
|
|
|
@@ -327,8 +356,7 @@ def decode_field(
|
|
|
327
356
|
field_def: FieldDef,
|
|
328
357
|
data: bytearray | bytes,
|
|
329
358
|
env: dict[str, Any] | None = None,
|
|
330
|
-
|
|
331
|
-
enum_def_dict: dict[str, EnumDef] | None = None,
|
|
359
|
+
type_dict: TypeDict | None = None,
|
|
332
360
|
padding_alignment_bits: int = _DEFAULT_PADDING_ALIGNMENT_BITS,
|
|
333
361
|
) -> FieldInstance | None:
|
|
334
362
|
"""Decode a single field from a bytearray according to a field definition.
|
|
@@ -341,8 +369,9 @@ def decode_field(
|
|
|
341
369
|
The data to decode.
|
|
342
370
|
env : dict[str, Any] | None, optional
|
|
343
371
|
The environment for evaluating expressions, by default None.
|
|
344
|
-
|
|
345
|
-
|
|
372
|
+
type_dict : TypeDict | None, optional
|
|
373
|
+
Type dictionaries including structure and enum definitions,
|
|
374
|
+
by default None.
|
|
346
375
|
Returns
|
|
347
376
|
-------
|
|
348
377
|
FieldInstance | None
|
|
@@ -358,7 +387,7 @@ def decode_field(
|
|
|
358
387
|
byte_swap = _resolve_byte_swap(field_def, env)
|
|
359
388
|
if byte_swap:
|
|
360
389
|
info = _byte_swap_info(info, size)
|
|
361
|
-
resolved_type = _resolve_field_type(field_def.type,
|
|
390
|
+
resolved_type = _resolve_field_type(field_def.type, type_dict, env)
|
|
362
391
|
resolved_field_def = FieldDef(
|
|
363
392
|
name=field_def.name,
|
|
364
393
|
offset=offset,
|
|
@@ -374,40 +403,38 @@ def decode_field(
|
|
|
374
403
|
if isinstance(resolved_type, StructDef):
|
|
375
404
|
return FieldInstance(
|
|
376
405
|
field_def=resolved_field_def,
|
|
377
|
-
value=decode(resolved_type, bytearray(info.to_bytes),
|
|
378
|
-
struct_def_dict, enum_def_dict,
|
|
406
|
+
value=decode(resolved_type, bytearray(info.to_bytes), type_dict,
|
|
379
407
|
padding_alignment_bits),
|
|
380
408
|
)
|
|
381
409
|
if resolved_type == "bool":
|
|
382
410
|
return FieldInstance.from_value(resolved_field_def,
|
|
383
411
|
info.to_bool,
|
|
384
|
-
|
|
412
|
+
type_dict=type_dict)
|
|
385
413
|
if resolved_type == "signed int":
|
|
386
414
|
return FieldInstance.from_value(resolved_field_def,
|
|
387
415
|
info.to_signed_int,
|
|
388
|
-
|
|
416
|
+
type_dict=type_dict)
|
|
389
417
|
if resolved_type in ["int", "unsigned int"]:
|
|
390
418
|
return FieldInstance.from_value(resolved_field_def,
|
|
391
419
|
info.to_unsigned_int,
|
|
392
|
-
|
|
420
|
+
type_dict=type_dict)
|
|
393
421
|
if resolved_type == "float":
|
|
394
422
|
return FieldInstance.from_value(resolved_field_def,
|
|
395
423
|
info.to_float,
|
|
396
|
-
|
|
424
|
+
type_dict=type_dict)
|
|
397
425
|
if resolved_type in ["bytearray", "bytes"]:
|
|
398
426
|
return FieldInstance.from_value(resolved_field_def,
|
|
399
427
|
info.to_bytes,
|
|
400
|
-
|
|
428
|
+
type_dict=type_dict)
|
|
401
429
|
return FieldInstance.from_value(resolved_field_def,
|
|
402
430
|
info.raw_value,
|
|
403
|
-
|
|
431
|
+
type_dict=type_dict)
|
|
404
432
|
|
|
405
433
|
|
|
406
434
|
def decode(
|
|
407
435
|
struct_def: StructDef | list[FieldDef],
|
|
408
436
|
data: bytearray | bytes,
|
|
409
|
-
|
|
410
|
-
enum_def_dict: dict[str, EnumDef] | None = None,
|
|
437
|
+
type_dict: TypeDict | None = None,
|
|
411
438
|
padding_alignment_bits: int = _DEFAULT_PADDING_ALIGNMENT_BITS,
|
|
412
439
|
) -> StructInstance:
|
|
413
440
|
"""Decode a bytearray into field values according to a layout.
|
|
@@ -418,10 +445,9 @@ def decode(
|
|
|
418
445
|
The definitions of the fields to decode.
|
|
419
446
|
data : bytearray | bytes
|
|
420
447
|
The data to decode.
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
A dictionary of enum definitions, by default None.
|
|
448
|
+
type_dict : TypeDict | None, optional
|
|
449
|
+
Type dictionaries including structure and enum definitions,
|
|
450
|
+
by default None.
|
|
425
451
|
padding_alignment_bits : int, optional
|
|
426
452
|
The padding alignment boundary in bits, by default 32.
|
|
427
453
|
Returns
|
|
@@ -471,8 +497,8 @@ def decode(
|
|
|
471
497
|
if field_def.repeat is None or field_def.repeat <= 1:
|
|
472
498
|
resolved_offset = _resolve_offset(field_def, env)
|
|
473
499
|
append_padding_until(resolved_offset)
|
|
474
|
-
field_instance = decode_field(field_def, data, env,
|
|
475
|
-
|
|
500
|
+
field_instance = decode_field(field_def, data, env, type_dict,
|
|
501
|
+
padding_alignment_bits)
|
|
476
502
|
if field_instance is not None:
|
|
477
503
|
env[field_instance.field_def.name] = field_instance.value
|
|
478
504
|
result.append_field_instance(field_instance)
|
|
@@ -487,8 +513,7 @@ def decode(
|
|
|
487
513
|
field_def_repeat = _split_repeated_field(field_def, i, env,
|
|
488
514
|
current_offset)
|
|
489
515
|
field_instance = decode_field(field_def_repeat, data, env,
|
|
490
|
-
|
|
491
|
-
padding_alignment_bits)
|
|
516
|
+
type_dict, padding_alignment_bits)
|
|
492
517
|
if field_instance is not None:
|
|
493
518
|
env[field_instance.field_def.name] = field_instance.value
|
|
494
519
|
result.append_field_instance(field_instance)
|
|
@@ -501,17 +526,19 @@ def decode(
|
|
|
501
526
|
|
|
502
527
|
|
|
503
528
|
def _get_struct_def(
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
529
|
+
struct_def_name: str,
|
|
530
|
+
type_dict: TypeDict | None = None,
|
|
531
|
+
env: dict[str, Any] | None = None,
|
|
532
|
+
) -> StructDef | str | None:
|
|
507
533
|
"""Get a structure definition from a dictionary or evaluate it.
|
|
508
534
|
|
|
509
535
|
Parameters
|
|
510
536
|
----------
|
|
511
537
|
struct_def_name : str
|
|
512
538
|
The name of the structure definition to get.
|
|
513
|
-
|
|
514
|
-
|
|
539
|
+
type_dict : TypeDict | None, optional
|
|
540
|
+
Type dictionaries including structure and enum definitions,
|
|
541
|
+
by default None.
|
|
515
542
|
env : dict[str, Any] | None, optional
|
|
516
543
|
The environment for evaluating the structure definition,
|
|
517
544
|
by default None.
|
|
@@ -521,8 +548,10 @@ def _get_struct_def(
|
|
|
521
548
|
StructDef | str | None
|
|
522
549
|
The structure definition, primitive type, or None if not found.
|
|
523
550
|
"""
|
|
524
|
-
if
|
|
525
|
-
|
|
551
|
+
struct_dict = None if type_dict is None else type_dict.struct_dict
|
|
552
|
+
|
|
553
|
+
if struct_dict and struct_def_name in struct_dict:
|
|
554
|
+
return struct_dict[struct_def_name]
|
|
526
555
|
|
|
527
556
|
stleval = SltEval(env)
|
|
528
557
|
try:
|
|
@@ -532,7 +561,7 @@ def _get_struct_def(
|
|
|
532
561
|
|
|
533
562
|
if isinstance(eval_result, str) and eval_result in _PRIMITIVE_TYPES:
|
|
534
563
|
return eval_result
|
|
535
|
-
if (isinstance(eval_result, str) and
|
|
536
|
-
and eval_result in
|
|
537
|
-
return
|
|
564
|
+
if (isinstance(eval_result, str) and struct_dict
|
|
565
|
+
and eval_result in struct_dict):
|
|
566
|
+
return struct_dict[eval_result]
|
|
538
567
|
return None
|
|
@@ -3,9 +3,10 @@ from __future__ import annotations
|
|
|
3
3
|
|
|
4
4
|
import json
|
|
5
5
|
import re
|
|
6
|
+
from collections.abc import MutableMapping
|
|
6
7
|
from dataclasses import dataclass, field
|
|
7
8
|
from functools import total_ordering
|
|
8
|
-
from typing import Any
|
|
9
|
+
from typing import Any, Dict, Iterator, Optional
|
|
9
10
|
|
|
10
11
|
from sltcalc import SltEval
|
|
11
12
|
from sltcore import Info, InfoSize
|
|
@@ -336,10 +337,10 @@ class FieldInstance:
|
|
|
336
337
|
def from_value(cls,
|
|
337
338
|
field_def: FieldDef,
|
|
338
339
|
value: Any,
|
|
339
|
-
|
|
340
|
+
type_dict: "TypeDict | None" = None,
|
|
340
341
|
is_padding: bool = False) -> "FieldInstance":
|
|
341
342
|
"""Create a FieldInstance and attach a matched enum item if any."""
|
|
342
|
-
enum_def = cls._resolve_enum_def(field_def,
|
|
343
|
+
enum_def = cls._resolve_enum_def(field_def, type_dict)
|
|
343
344
|
enum_item = cls._resolve_enum_item(enum_def, value)
|
|
344
345
|
return cls(field_def=field_def,
|
|
345
346
|
value=value,
|
|
@@ -347,17 +348,19 @@ class FieldInstance:
|
|
|
347
348
|
is_padding=is_padding)
|
|
348
349
|
|
|
349
350
|
@staticmethod
|
|
350
|
-
def _resolve_enum_def(
|
|
351
|
-
|
|
352
|
-
enum_def_dict: dict[str, EnumDef] | None) -> EnumDef | None:
|
|
351
|
+
def _resolve_enum_def(field_def: FieldDef,
|
|
352
|
+
type_dict: "TypeDict | None") -> EnumDef | None:
|
|
353
353
|
"""Resolve enum definition from field metadata or lookup dictionary."""
|
|
354
|
-
if
|
|
354
|
+
if type_dict is None:
|
|
355
|
+
return None
|
|
356
|
+
enum_dict = type_dict.enum_dict
|
|
357
|
+
if len(enum_dict) == 0:
|
|
355
358
|
return None
|
|
356
359
|
if field_def.enum_def_name is not None:
|
|
357
|
-
return
|
|
358
|
-
if isinstance(field_def.type, str) and field_def.type in
|
|
359
|
-
return
|
|
360
|
-
return
|
|
360
|
+
return enum_dict.get(field_def.enum_def_name)
|
|
361
|
+
if isinstance(field_def.type, str) and field_def.type in enum_dict:
|
|
362
|
+
return enum_dict[field_def.type]
|
|
363
|
+
return enum_dict.get(field_def.name)
|
|
361
364
|
|
|
362
365
|
@staticmethod
|
|
363
366
|
def _resolve_enum_item(enum_def: EnumDef | None,
|
|
@@ -596,3 +599,82 @@ class StructInstance:
|
|
|
596
599
|
|
|
597
600
|
if max_end_offset > self.size:
|
|
598
601
|
self.size = max_end_offset
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
@dataclass
|
|
605
|
+
class EnumDict(MutableMapping):
|
|
606
|
+
"""A dictionary-like container for EnumDef objects."""
|
|
607
|
+
_items: Dict[str, "EnumDef"]
|
|
608
|
+
|
|
609
|
+
def __init__(self, items: Optional[Dict[str, "EnumDef"]] = None):
|
|
610
|
+
self._items = items or {}
|
|
611
|
+
|
|
612
|
+
def __getitem__(self, key: str) -> "EnumDef":
|
|
613
|
+
return self._items[key]
|
|
614
|
+
|
|
615
|
+
def __setitem__(self, key: str, value: "EnumDef"):
|
|
616
|
+
self._items[key] = value
|
|
617
|
+
|
|
618
|
+
def __delitem__(self, key: str):
|
|
619
|
+
del self._items[key]
|
|
620
|
+
|
|
621
|
+
def __iter__(self) -> Iterator[str]:
|
|
622
|
+
return iter(self._items)
|
|
623
|
+
|
|
624
|
+
def __len__(self) -> int:
|
|
625
|
+
return len(self._items)
|
|
626
|
+
|
|
627
|
+
def items_dict(self) -> Dict[str, "EnumDef"]:
|
|
628
|
+
"""Return the underlying dictionary of EnumDef objects.
|
|
629
|
+
Returns:
|
|
630
|
+
Dict[str, EnumDef]: The underlying dictionary
|
|
631
|
+
of EnumDef objects."""
|
|
632
|
+
return self._items
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
@dataclass
|
|
636
|
+
class StructDict(MutableMapping):
|
|
637
|
+
"""A dictionary-like container for StructDef objects. """
|
|
638
|
+
_items: Dict[str, "StructDef"]
|
|
639
|
+
|
|
640
|
+
def __init__(self, items: Optional[Dict[str, "StructDef"]] = None):
|
|
641
|
+
self._items = items or {}
|
|
642
|
+
|
|
643
|
+
def __getitem__(self, key: str) -> "StructDef":
|
|
644
|
+
return self._items[key]
|
|
645
|
+
|
|
646
|
+
def __setitem__(self, key: str, value: "StructDef"):
|
|
647
|
+
self._items[key] = value
|
|
648
|
+
|
|
649
|
+
def __delitem__(self, key: str):
|
|
650
|
+
del self._items[key]
|
|
651
|
+
|
|
652
|
+
def __iter__(self) -> Iterator[str]:
|
|
653
|
+
return iter(self._items)
|
|
654
|
+
|
|
655
|
+
def __len__(self) -> int:
|
|
656
|
+
return len(self._items)
|
|
657
|
+
|
|
658
|
+
def items_dict(self) -> Dict[str, "StructDef"]:
|
|
659
|
+
"""Return the underlying dictionary of StructDef objects.
|
|
660
|
+
Returns:
|
|
661
|
+
Dict[str, StructDef]: The underlying dictionary
|
|
662
|
+
of StructDef objects."""
|
|
663
|
+
return self._items
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
@dataclass
|
|
667
|
+
class TypeDict:
|
|
668
|
+
"""A dictionary-like container for EnumDef and StructDef objects."""
|
|
669
|
+
enum_dict: EnumDict
|
|
670
|
+
struct_dict: StructDict
|
|
671
|
+
|
|
672
|
+
def __init__(
|
|
673
|
+
self,
|
|
674
|
+
enum_dict: Optional[Dict[str, "EnumDef"]] = None,
|
|
675
|
+
struct_dict: Optional[Dict[str, "StructDef"]] = None,
|
|
676
|
+
):
|
|
677
|
+
"""Initialize TypeDict with optional EnumDef
|
|
678
|
+
and StructDef dictionaries."""
|
|
679
|
+
self.enum_dict = EnumDict(enum_dict)
|
|
680
|
+
self.struct_dict = StructDict(struct_dict)
|
|
@@ -7,9 +7,8 @@ import pytest
|
|
|
7
7
|
from sltcore import InfoSize
|
|
8
8
|
|
|
9
9
|
from sltcodec import (PRIMITIVE_TYPES, EnumDef, FieldDef, FieldInstance,
|
|
10
|
-
StructDef, StructInstance, decode, encode,
|
|
11
|
-
|
|
12
|
-
save_enum_def_dict, save_struct_def_dict)
|
|
10
|
+
StructDef, StructInstance, TypeDict, decode, encode,
|
|
11
|
+
load_type_dict, save_type_dict)
|
|
13
12
|
from sltcodec.codec import decode_field
|
|
14
13
|
|
|
15
14
|
|
|
@@ -402,10 +401,9 @@ def test_decode_uses_enum_def_dict_to_set_enum_item():
|
|
|
402
401
|
offset=InfoSize(0, 0),
|
|
403
402
|
size=InfoSize(1, 0),
|
|
404
403
|
type="unsigned int")
|
|
404
|
+
type_dict = TypeDict(enum_dict={"status": enum_def})
|
|
405
405
|
|
|
406
|
-
decoded = decode([field_def],
|
|
407
|
-
bytearray(b"\x02"),
|
|
408
|
-
enum_def_dict={"status": enum_def})
|
|
406
|
+
decoded = decode([field_def], bytearray(b"\x02"), type_dict=type_dict)
|
|
409
407
|
|
|
410
408
|
assert decoded.field_instances[0].value == 2
|
|
411
409
|
assert decoded.field_instances[0].enum_item == ("NG", 2)
|
|
@@ -421,7 +419,7 @@ def test_field_instance_from_value_sets_enum_item_from_field_enum_def():
|
|
|
421
419
|
enum_def_name=enum_def.name)
|
|
422
420
|
|
|
423
421
|
field_instance = FieldInstance.from_value(
|
|
424
|
-
field_def, 1,
|
|
422
|
+
field_def, 1, type_dict=TypeDict(enum_dict={enum_def.name: enum_def}))
|
|
425
423
|
|
|
426
424
|
assert field_instance.enum_item == ("MANUAL", 1)
|
|
427
425
|
|
|
@@ -460,8 +458,8 @@ def test_struct_instance_size_json_round_trip():
|
|
|
460
458
|
assert struct_instance.size == InfoSize(8, 0)
|
|
461
459
|
|
|
462
460
|
|
|
463
|
-
def
|
|
464
|
-
"""Test
|
|
461
|
+
def test_type_dict_load_and_save_struct_dict(tmp_path: Path):
|
|
462
|
+
"""Test TypeDict save/load for struct definitions."""
|
|
465
463
|
struct_def = StructDef(name="ValueStruct",
|
|
466
464
|
description="Single value struct",
|
|
467
465
|
fields=[
|
|
@@ -473,18 +471,19 @@ def test_struct_def_dict_load_and_save(tmp_path: Path):
|
|
|
473
471
|
])
|
|
474
472
|
path = tmp_path / "field_defs.json"
|
|
475
473
|
|
|
476
|
-
|
|
477
|
-
saved_field = json.loads(
|
|
474
|
+
save_type_dict(path, TypeDict(struct_dict={"value": struct_def}))
|
|
475
|
+
saved_field = json.loads(
|
|
476
|
+
path.read_text())["struct_dict"]["value"]["fields"][0]
|
|
478
477
|
|
|
479
478
|
assert isinstance(saved_field["offset"], dict)
|
|
480
479
|
assert isinstance(saved_field["size"], dict)
|
|
481
|
-
loaded =
|
|
480
|
+
loaded = load_type_dict(path)
|
|
482
481
|
|
|
483
|
-
assert loaded["value"] == struct_def
|
|
482
|
+
assert loaded.struct_dict["value"] == struct_def
|
|
484
483
|
|
|
485
484
|
|
|
486
|
-
def
|
|
487
|
-
"""Test
|
|
485
|
+
def test_type_dict_load_and_save_enum_dict(tmp_path: Path):
|
|
486
|
+
"""Test TypeDict save/load for enum definitions."""
|
|
488
487
|
enum_def = EnumDef(name="Status",
|
|
489
488
|
description="Status enum",
|
|
490
489
|
values={
|
|
@@ -493,10 +492,10 @@ def test_enum_def_dict_load_and_save(tmp_path: Path):
|
|
|
493
492
|
})
|
|
494
493
|
path = tmp_path / "enum_defs.json"
|
|
495
494
|
|
|
496
|
-
|
|
497
|
-
loaded =
|
|
495
|
+
save_type_dict(path, TypeDict(enum_dict={"status": enum_def}))
|
|
496
|
+
loaded = load_type_dict(path)
|
|
498
497
|
|
|
499
|
-
assert loaded["status"] == enum_def
|
|
498
|
+
assert loaded.enum_dict["status"] == enum_def
|
|
500
499
|
|
|
501
500
|
|
|
502
501
|
def test_struct_def_to_json_from_json_round_trip():
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
from .codec import (PRIMITIVE_TYPES, decode, encode, encode_field,
|
|
2
|
-
load_enum_def_dict, load_struct_def_dict,
|
|
3
|
-
save_enum_def_dict, save_struct_def_dict)
|
|
4
|
-
from .types import EnumDef, FieldDef, FieldInstance, StructDef, StructInstance
|
|
5
|
-
|
|
6
|
-
__all__ = [
|
|
7
|
-
"PRIMITIVE_TYPES",
|
|
8
|
-
"EnumDef",
|
|
9
|
-
"FieldDef",
|
|
10
|
-
"FieldInstance",
|
|
11
|
-
"StructDef",
|
|
12
|
-
"StructInstance",
|
|
13
|
-
"decode",
|
|
14
|
-
"encode",
|
|
15
|
-
"encode_field",
|
|
16
|
-
"load_enum_def_dict",
|
|
17
|
-
"load_struct_def_dict",
|
|
18
|
-
"save_enum_def_dict",
|
|
19
|
-
"save_struct_def_dict",
|
|
20
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|