| 54 | return cls |
| 55 | |
| 56 | class Field: |
| 57 | def __init__(self, typ, off, bit_width=None, bit_off=0, *, name=None, idx=0): |
| 58 | self.typ, self.off, self.bit_width, self.bit_off, self.name, self.idx = typ, off, bit_width, bit_off, name, idx |
| 59 | |
| 60 | def __set_name__(self, owner, name): |
| 61 | entry = (name, self.typ, self.off) + ((self.bit_width, self.bit_off) if self.bit_width else ()) |
| 62 | if hasattr(owner, "_real_fields_"): owner._real_fields_.append(entry) |
| 63 | else: setattr(owner, "_real_fields_", [entry]) |
| 64 | self.name, self.idx = name, len(owner._real_fields_) - 1 |
| 65 | |
| 66 | # lazily resolve field descriptors |
| 67 | def _resolve(self, cls): |
| 68 | if self.bit_width: # handle bitfields ourselves |
| 69 | sl, set_mask = slice(self.off, self.off+(sz:=ceildiv(self.bit_width+self.bit_off, 8))), ~((mask:=(1 << self.bit_width) - 1) << self.bit_off) |
| 70 | def b2i(obj): return int.from_bytes(memoryview(obj).cast("B")[sl], sys.byteorder) |
| 71 | def bset(obj, v): memoryview(obj).cast("B")[sl] = ((b2i(obj) & set_mask) | v << self.bit_off).to_bytes(sz, sys.byteorder) |
| 72 | # FIXME: signedness |
| 73 | cf = property(lambda obj: b2i(obj) >> self.bit_off & mask, bset) |
| 74 | # pull the CField descriptor from a dummy class, zero length arrays are so ctypes manages references to child objects for us |
| 75 | else: cf = type(self.name, (ctypes.Structure,), {"_layout_": "ms", "_pack_": 1, "_fields_": [(str(i), ctypes.c_byte*0) for i in range(self.idx)] + |
| 76 | [("_", ctypes.c_byte * self.off), ("v", self.typ)]}).v # type: ignore |
| 77 | setattr(cls, self.name, cf) |
| 78 | return cf |
| 79 | |
| 80 | def __get__(self, obj, objtype=None): return self._resolve(objtype).__get__(obj, objtype) if objtype else self |
| 81 | def __set__(self, obj, value): self._resolve(obj.__class__).__set__(obj, value) |
| 82 | |
| 83 | @functools.cache |
| 84 | def init_c_struct_t(sz:int, fields: tuple[tuple, ...]): |
no outgoing calls
no test coverage detected
searching dependent graphs…