From b2bcec5f7c77285b50ee5445cc931e776f6aa06d Mon Sep 17 00:00:00 2001 From: Gabriel Burca Date: Wed, 18 Dec 2024 14:59:42 -0600 Subject: [PATCH] Fix handling of repeating groups with padding - If the group specifies a blockLength greater than the calculated (natural) group size, we need to add padding after each group. - The groupSizeEncoding must report the specified blockLength so the decoder can skip over padding. - Fix a typo in the schema --- .gitignore | 2 ++ sbe/__init__.py | 6 +++++- tests/dat/example-schema.xml | 2 +- tests/test_sbe.py | 5 +++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 364b0d1..033f3e5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /dist/ /sbe.egg-info/ __pycache__/ +.venv +.eggs diff --git a/sbe/__init__.py b/sbe/__init__.py index d4bda2e..6d3e769 100644 --- a/sbe/__init__.py +++ b/sbe/__init__.py @@ -758,8 +758,12 @@ def _walk_fields_encode(schema: Schema, fields: List[Union[Group, Field]], f.blockLength, Cursor(0)) if block_length is None: block_length = struct.calcsize("<" + ''.join(fmt1)) + if f.blockLength: + assert f.blockLength >= block_length + if f.blockLength and f.blockLength > block_length: + fmt1.append(str(f.blockLength - block_length) + 'x') - dimension = {"numInGroup": len(obj[f.name]), "blockLength": block_length or f.blockLength or 0} + dimension = {"numInGroup": len(obj[f.name]), "blockLength": f.blockLength or block_length or 0} dimension_fmt = _pack_format(schema, f.dimensionType) fmt.extend(dimension_fmt) diff --git a/tests/dat/example-schema.xml b/tests/dat/example-schema.xml index 746e7d7..c646a33 100644 --- a/tests/dat/example-schema.xml +++ b/tests/dat/example-schema.xml @@ -80,7 +80,7 @@ - + diff --git a/tests/test_sbe.py b/tests/test_sbe.py index 4325e0e..587033b 100644 --- a/tests/test_sbe.py +++ b/tests/test_sbe.py @@ -30,9 +30,10 @@ def test_blockLength(): {'numbers': 456}]}) # BlockHeader = 8b # Body = 2b year + 2b padding + # GroupHeader = 4b # Repeating group = 2 * (4b numbers + 2b padding) - expLen = 8 + 4 + 2*6 - assert len(encoded) == expLen, "Encoded SBE not padded properly" + expLen = 8 + 4 + 4 + 2*6 + assert len(encoded) == expLen, f"Encoded SBE not padded properly. Expected {expLen} actual {len(encoded)}" decoded = s.decode(encoded) assert decoded.value['year'] == 1990