sltcodec 1.1.0__tar.gz → 1.2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sltcodec
3
- Version: 1.1.0
3
+ Version: 1.2.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
@@ -236,6 +236,44 @@ bytearray(b"\x01\x07") StructInstance(struct_def=StructDef(...), field_instances
236
236
  bytearray(b"\x02?\xc0\x00\x00") StructInstance(struct_def=StructDef(...), field_instances=[...])
237
237
  ```
238
238
 
239
+ ## Enum Definitions
240
+
241
+ `FieldDef.enum_def_name` holds only the name of an `EnumDef`, not the definition
242
+ itself. Pass the actual definitions via an `enum_def_dict` (mapping name to
243
+ `EnumDef`) to `decode` / `encode` so the matching `EnumDef` can be resolved and
244
+ attached as `FieldInstance.enum_item`.
245
+
246
+ ```python
247
+ from sltcore import InfoSize
248
+ from sltcodec import EnumDef, FieldDef, decode
249
+
250
+ status_enum = EnumDef(name="Status", values={"OK": 0, "NG": 1})
251
+
252
+ struct_def = [
253
+ FieldDef(name="status",
254
+ offset=InfoSize(0, 0),
255
+ size=InfoSize(1, 0),
256
+ type="unsigned int",
257
+ enum_def_name="Status"),
258
+ ]
259
+
260
+ decoded = decode(struct_def, bytearray(b"\x01"),
261
+ enum_def_dict={"Status": status_enum})
262
+
263
+ print(decoded.field_instances[0].value)
264
+ print(decoded.field_instances[0].enum_item)
265
+ ```
266
+
267
+ Output:
268
+
269
+ ```python
270
+ 1
271
+ ('NG', 1)
272
+ ```
273
+
274
+ You can also persist enum definitions by name with
275
+ `save_enum_def_dict` / `load_enum_def_dict`, mirroring `StructDef` dictionaries.
276
+
239
277
  ## Development
240
278
 
241
279
  ```bash
@@ -219,6 +219,44 @@ bytearray(b"\x01\x07") StructInstance(struct_def=StructDef(...), field_instances
219
219
  bytearray(b"\x02?\xc0\x00\x00") StructInstance(struct_def=StructDef(...), field_instances=[...])
220
220
  ```
221
221
 
222
+ ## Enum Definitions
223
+
224
+ `FieldDef.enum_def_name` holds only the name of an `EnumDef`, not the definition
225
+ itself. Pass the actual definitions via an `enum_def_dict` (mapping name to
226
+ `EnumDef`) to `decode` / `encode` so the matching `EnumDef` can be resolved and
227
+ attached as `FieldInstance.enum_item`.
228
+
229
+ ```python
230
+ from sltcore import InfoSize
231
+ from sltcodec import EnumDef, FieldDef, decode
232
+
233
+ status_enum = EnumDef(name="Status", values={"OK": 0, "NG": 1})
234
+
235
+ struct_def = [
236
+ FieldDef(name="status",
237
+ offset=InfoSize(0, 0),
238
+ size=InfoSize(1, 0),
239
+ type="unsigned int",
240
+ enum_def_name="Status"),
241
+ ]
242
+
243
+ decoded = decode(struct_def, bytearray(b"\x01"),
244
+ enum_def_dict={"Status": status_enum})
245
+
246
+ print(decoded.field_instances[0].value)
247
+ print(decoded.field_instances[0].enum_item)
248
+ ```
249
+
250
+ Output:
251
+
252
+ ```python
253
+ 1
254
+ ('NG', 1)
255
+ ```
256
+
257
+ You can also persist enum definitions by name with
258
+ `save_enum_def_dict` / `load_enum_def_dict`, mirroring `StructDef` dictionaries.
259
+
222
260
  ## Development
223
261
 
224
262
  ```bash
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sltcodec"
3
- version = "1.1.0"
3
+ version = "1.2.0"
4
4
  description = "Decode and encode bytearrays according to struct layout definitions using sltcore."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -368,7 +368,7 @@ def decode_field(
368
368
  repeat=field_def.repeat,
369
369
  description=field_def.description,
370
370
  range_expression=field_def.range_expression,
371
- enum_def=field_def.enum_def,
371
+ enum_def_name=field_def.enum_def_name,
372
372
  byte_swap=byte_swap,
373
373
  )
374
374
  if isinstance(resolved_type, StructDef):
@@ -104,8 +104,9 @@ class FieldDef:
104
104
  default=None, metadata={"desc": "The description of the field"})
105
105
  range_expression: str | None = field(
106
106
  default=None, metadata={"desc": "The value range expression"})
107
- enum_def: EnumDef | None = field(
108
- default=None, metadata={"desc": "The enum definition for the field"})
107
+ enum_def_name: str | None = field(
108
+ default=None,
109
+ metadata={"desc": "The name of the enum definition for the field"})
109
110
  byte_swap: bool | str = field(
110
111
  default=False,
111
112
  metadata={"desc": "Whether to reverse the field byte order"})
@@ -137,7 +138,7 @@ class FieldDef:
137
138
  repeat=None,
138
139
  description=self.description,
139
140
  range_expression=split_range_expression,
140
- enum_def=self.enum_def,
141
+ enum_def_name=self.enum_def_name,
141
142
  byte_swap=split_byte_swap)
142
143
 
143
144
  @staticmethod
@@ -184,8 +185,8 @@ class FieldDef:
184
185
  self.description,
185
186
  "range_expression":
186
187
  self.range_expression,
187
- "enum_def":
188
- None if self.enum_def is None else self.enum_def.serialize(),
188
+ "enum_def_name":
189
+ self.enum_def_name,
189
190
  "byte_swap":
190
191
  self.byte_swap,
191
192
  }
@@ -205,7 +206,7 @@ class FieldDef:
205
206
  repeat = data.get("repeat")
206
207
  description = data.get("description")
207
208
  range_expression = data.get("range_expression")
208
- enum_def_data = data.get("enum_def")
209
+ enum_def_name = data.get("enum_def_name")
209
210
  byte_swap = data.get("byte_swap", False)
210
211
 
211
212
  def _deserialize_info_like(value: Any) -> Any:
@@ -242,14 +243,6 @@ class FieldDef:
242
243
  else:
243
244
  type_value = type_data
244
245
 
245
- if enum_def_data is None:
246
- enum_def = None
247
- elif (isinstance(enum_def_data, dict)
248
- and enum_def_data.get("__type__") == "EnumDef"):
249
- enum_def = EnumDef.deserialize(enum_def_data)
250
- else:
251
- enum_def = None
252
-
253
246
  return cls(
254
247
  name=name,
255
248
  offset=offset,
@@ -259,7 +252,7 @@ class FieldDef:
259
252
  repeat=repeat,
260
253
  description=description,
261
254
  range_expression=range_expression,
262
- enum_def=enum_def,
255
+ enum_def_name=enum_def_name,
263
256
  byte_swap=byte_swap,
264
257
  )
265
258
 
@@ -279,7 +272,7 @@ class FieldDef:
279
272
  -1 if self.repeat is None else self.repeat,
280
273
  "" if self.description is None else self.description,
281
274
  "" if self.range_expression is None else self.range_expression,
282
- self._sortable_enum_type(self.enum_def),
275
+ "" if self.enum_def_name is None else self.enum_def_name,
283
276
  self._sortable_byte_swap(self.byte_swap),
284
277
  )
285
278
 
@@ -297,19 +290,6 @@ class FieldDef:
297
290
  return (0, json.dumps(value.to_dict(), sort_keys=True))
298
291
  return (1, value)
299
292
 
300
- @staticmethod
301
- def _sortable_enum_type(value: EnumDef | None) -> str:
302
- """Build a comparable key for enum definition metadata."""
303
- if value is None:
304
- return ""
305
- return json.dumps(
306
- {
307
- "name": value.name,
308
- "description": value.description,
309
- "values": value.values,
310
- },
311
- sort_keys=True)
312
-
313
293
  @staticmethod
314
294
  def _sortable_byte_swap(value: bool | str) -> tuple[int, str]:
315
295
  """Build a comparable key for a byte-swap flag or expression."""
@@ -369,10 +349,10 @@ class FieldInstance:
369
349
  field_def: FieldDef,
370
350
  enum_def_dict: dict[str, EnumDef] | None) -> EnumDef | None:
371
351
  """Resolve enum definition from field metadata or lookup dictionary."""
372
- if field_def.enum_def is not None:
373
- return field_def.enum_def
374
352
  if not enum_def_dict:
375
353
  return None
354
+ if field_def.enum_def_name is not None:
355
+ return enum_def_dict.get(field_def.enum_def_name)
376
356
  if isinstance(field_def.type, str) and field_def.type in enum_def_dict:
377
357
  return enum_def_dict[field_def.type]
378
358
  return enum_def_dict.get(field_def.name)
@@ -179,7 +179,7 @@ def test_repeated_field_preserves_range_and_enum_metadata():
179
179
  type="unsigned int",
180
180
  repeat=2,
181
181
  range_expression="0 <= value <= 255",
182
- enum_def=enum_def)
182
+ enum_def_name=enum_def.name)
183
183
 
184
184
  encoded = encode(
185
185
  StructInstance(struct_def=StructDef(fields=[field_def]),
@@ -192,8 +192,8 @@ def test_repeated_field_preserves_range_and_enum_metadata():
192
192
  "0 <= value[0] <= 255")
193
193
  assert decoded.field_instances[1].field_def.range_expression == (
194
194
  "0 <= value[1] <= 255")
195
- assert decoded.field_instances[0].field_def.enum_def == enum_def
196
- assert decoded.field_instances[1].field_def.enum_def == enum_def
195
+ assert decoded.field_instances[0].field_def.enum_def_name == enum_def.name
196
+ assert decoded.field_instances[1].field_def.enum_def_name == enum_def.name
197
197
 
198
198
 
199
199
  def test_split_repeat_replaces_name_in_range_expression():
@@ -242,23 +242,15 @@ def test_field_def_to_json_from_json_round_trip():
242
242
  repeat=3,
243
243
  description="A repeated value",
244
244
  range_expression="0 <= value <= 255",
245
- enum_def=enum_def)
245
+ enum_def_name=enum_def.name)
246
246
 
247
247
  payload = field_def.to_json()
248
248
  restored = FieldDef.from_json(payload)
249
249
 
250
250
  assert restored == field_def
251
251
  assert restored.range_expression == "0 <= value <= 255"
252
- assert restored.enum_def == enum_def
253
- assert restored.to_dict()["enum_def"] == {
254
- "__type__": "EnumDef",
255
- "name": "ValueKind",
256
- "description": None,
257
- "values": {
258
- member.name: member.value
259
- for member in ValueKind
260
- },
261
- }
252
+ assert restored.enum_def_name == enum_def.name
253
+ assert restored.to_dict()["enum_def_name"] == "ValueKind"
262
254
 
263
255
 
264
256
  def test_field_def_byte_swap_json_round_trip():
@@ -425,9 +417,10 @@ def test_field_instance_from_value_sets_enum_item_from_field_enum_def():
425
417
  offset=InfoSize(0, 0),
426
418
  size=InfoSize(1, 0),
427
419
  type="unsigned int",
428
- enum_def=enum_def)
420
+ enum_def_name=enum_def.name)
429
421
 
430
- field_instance = FieldInstance.from_value(field_def, 1)
422
+ field_instance = FieldInstance.from_value(
423
+ field_def, 1, enum_def_dict={enum_def.name: enum_def})
431
424
 
432
425
  assert field_instance.enum_item == ("MANUAL", 1)
433
426
 
@@ -74,7 +74,7 @@ wheels = [
74
74
 
75
75
  [[package]]
76
76
  name = "sltcodec"
77
- version = "1.0.0"
77
+ version = "1.1.0"
78
78
  source = { editable = "." }
79
79
  dependencies = [
80
80
  { name = "sltcalc" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes