Skip to content

Commit bd3ff53

Browse files
committed
fix nested struct unpack
1 parent cc86c65 commit bd3ff53

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

cstruct/mem_cstruct.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class MemCStruct(AbstractCStruct):
5656
"""
5757

5858
__mem__ = None
59+
__base__ = 0
5960

6061
def unpack_from(self, buffer: Optional[bytes], offset: int = 0, flexible_array_length: Optional[int] = None) -> bool:
6162
"""
@@ -101,7 +102,7 @@ def pack(self) -> bytes:
101102
Returns:
102103
bytes: The packed structure
103104
"""
104-
return self.__mem__.raw[:-1] # the buffer is one item larger than its size and the last element is NUL
105+
return self.__mem__.raw[self.__base__ : self.__base__ + self.size]
105106

106107
def set_flexible_array_length(self, flexible_array_length: Optional[int]) -> None:
107108
"""

tests/test_nested.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,52 @@ def test_nested_anonymous_union_struct():
210210
assert o1.format1.field1 == 11
211211
assert o1.format1.field2 == 12
212212
assert o1.format1.field3 == 13
213+
214+
215+
def test_nested_struct_offset():
216+
cstruct.parse(
217+
"""
218+
struct op_a {
219+
int a;
220+
};
221+
222+
struct op_b {
223+
char a;
224+
char b;
225+
char c;
226+
};
227+
""",
228+
__byte_order__=cstruct.LITTLE_ENDIAN,
229+
)
230+
231+
Op = cstruct.parse(
232+
"""
233+
struct op {
234+
char preamble[10];
235+
uint64_t magic;
236+
union {
237+
struct op_a a_op;
238+
struct op_b b_op;
239+
} u1;
240+
struct op_a aaa;
241+
};
242+
""",
243+
__byte_order__=cstruct.LITTLE_ENDIAN,
244+
)
245+
246+
o = Op()
247+
o.preamble = b'ciao_ciao'
248+
o.magic = 3771778641802345472
249+
o.u1.a_op.a = 2022
250+
o.aaa.a = 0x33333333
251+
assert o.u1.b_op.a == b'\xe6'
252+
assert o.u1.b_op.b == b'\x07'
253+
assert o.u1.b_op.c == b'\x00'
254+
assert o.__base__ == 0
255+
assert o.u1.__base__ >= 10
256+
assert o.u1.__base__ == o.u1.a_op.__base__
257+
assert o.u1.__base__ == o.u1.b_op.__base__
258+
assert o.aaa.__base__ > o.u1.__base__
259+
assert o.pack() == b'ciao_ciao\x00\x00\xbc\x08\xe4\xb0\x0cX4\xe6\x07\x00\x003333'
260+
assert o.u1.pack() == b'\xe6\x07\x00\x00'
261+
assert o.aaa.pack() == b'3333'

0 commit comments

Comments
 (0)