|
7 | 7 | import unittest |
8 | 8 | from enum import IntEnum |
9 | 9 |
|
10 | | -from libdestruct import array, c_int, c_long, c_short, c_uint, inflater, struct, ptr, ptr_to_self, array_of, enum, enum_of |
| 10 | +from typing import Annotated |
| 11 | + |
| 12 | +from libdestruct import array, c_int, c_long, c_short, c_uint, inflater, offset, struct, ptr, ptr_to_self, array_of, enum, enum_of |
11 | 13 |
|
12 | 14 |
|
13 | 15 | class StructMemberCollisionTest(unittest.TestCase): |
@@ -354,6 +356,59 @@ class s_t(struct): |
354 | 356 | self.assertEqual(s.coords[1].value, 20) |
355 | 357 |
|
356 | 358 |
|
| 359 | +class AnnotatedOffsetTest(unittest.TestCase): |
| 360 | + """Test Annotated[type, offset(N)] syntax for explicit field offsets.""" |
| 361 | + |
| 362 | + def test_annotated_offset_basic(self): |
| 363 | + """Annotated[c_int, offset(N)] places a field at the given offset.""" |
| 364 | + class s_t(struct): |
| 365 | + a: c_int |
| 366 | + b: Annotated[c_int, offset(8)] |
| 367 | + |
| 368 | + from libdestruct import size_of |
| 369 | + self.assertEqual(size_of(s_t), 12) # 8 + 4 |
| 370 | + |
| 371 | + def test_annotated_offset_read(self): |
| 372 | + """Values are read correctly from Annotated offset positions.""" |
| 373 | + import struct as pystruct |
| 374 | + |
| 375 | + class s_t(struct): |
| 376 | + a: c_int |
| 377 | + b: Annotated[c_int, offset(8)] |
| 378 | + |
| 379 | + memory = pystruct.pack("<i", 10) + b"\x00" * 4 + pystruct.pack("<i", 20) |
| 380 | + s = s_t.from_bytes(memory) |
| 381 | + self.assertEqual(s.a.value, 10) |
| 382 | + self.assertEqual(s.b.value, 20) |
| 383 | + |
| 384 | + def test_annotated_offset_with_subscript(self): |
| 385 | + """Annotated works with subscript syntax types.""" |
| 386 | + class s_t(struct): |
| 387 | + a: c_int |
| 388 | + data: Annotated[array[c_int, 2], offset(8)] |
| 389 | + |
| 390 | + from libdestruct import size_of |
| 391 | + self.assertEqual(size_of(s_t), 16) # 8 + 2*4 |
| 392 | + |
| 393 | + def test_annotated_offset_with_ptr(self): |
| 394 | + """Annotated works with ptr subscript syntax.""" |
| 395 | + class s_t(struct): |
| 396 | + a: c_int |
| 397 | + ref: Annotated[ptr[c_int], offset(8)] |
| 398 | + |
| 399 | + from libdestruct import size_of |
| 400 | + self.assertEqual(size_of(s_t), 16) # 8 + 8 |
| 401 | + |
| 402 | + def test_old_offset_syntax_still_works(self): |
| 403 | + """The old offset() default value syntax continues to work.""" |
| 404 | + class s_t(struct): |
| 405 | + a: c_int |
| 406 | + b: c_int = offset(8) |
| 407 | + |
| 408 | + from libdestruct import size_of |
| 409 | + self.assertEqual(size_of(s_t), 12) |
| 410 | + |
| 411 | + |
357 | 412 | class StructEqualityTest(unittest.TestCase): |
358 | 413 | def test_struct_eq_non_struct_returns_not_implemented(self): |
359 | 414 | """struct.__eq__ returns NotImplemented for non-struct values.""" |
|
0 commit comments