|
1 | 1 | from dataclasses import dataclass, field |
2 | 2 | from typing import Dict, Any, Optional |
| 3 | +import ctypes |
3 | 4 |
|
4 | 5 |
|
5 | 6 | # TODO: FIX THE FUCKING TYPE NAME CONVENTION. |
@@ -140,11 +141,14 @@ def add_field( |
140 | 141 | type_size=type_size, |
141 | 142 | ctype_complex_type=ctype_complex_type, |
142 | 143 | bitfield_size=bitfield_size, |
143 | | - offset=offset |
| 144 | + offset=offset, |
144 | 145 | ) |
145 | 146 | # Invalidate readiness cache |
146 | 147 | self._ready_cache = None |
147 | 148 |
|
| 149 | + def __sizeof__(self): |
| 150 | + return self.current_offset |
| 151 | + |
148 | 152 | def get_field(self, name: str) -> Field: |
149 | 153 | """Get a field by name.""" |
150 | 154 | return self.fields[name] |
@@ -211,20 +215,53 @@ def set_field_bitfield_size( |
211 | 215 | # Invalidate readiness cache |
212 | 216 | self._ready_cache = None |
213 | 217 |
|
214 | | - def set_field_ready(self, name: str, is_ready: bool = False) -> None: |
| 218 | + def set_field_ready(self, name: str, is_ready: bool = False, size_of_containing_type: Optional[int] = None) -> None: |
215 | 219 | """Mark a field as ready or not ready.""" |
216 | 220 | if name not in self.fields: |
217 | 221 | raise KeyError(f"Field '{name}' does not exist in node '{self.name}'") |
218 | 222 |
|
219 | 223 | self.fields[name].set_ready(is_ready) |
220 | 224 | self.fields[name].set_offset(self.current_offset) |
221 | | - self.current_offset += self._calculate_size(name) |
222 | | - |
| 225 | + self.current_offset += self._calculate_size(name, size_of_containing_type) |
223 | 226 | # Invalidate readiness cache |
224 | 227 | self._ready_cache = None |
225 | 228 |
|
226 | | - def _calculate_size(self, name: str) -> int: |
227 | | - pass |
| 229 | + def _calculate_size(self, name: str, size_of_containing_type: Optional[int] = None) -> int: |
| 230 | + processing_field = self.fields[name] |
| 231 | + # size_of_field will be in bytes |
| 232 | + if processing_field.type.__module__ == ctypes.__name__: |
| 233 | + size_of_field = ctypes.sizeof(processing_field.type) |
| 234 | + return size_of_field |
| 235 | + elif processing_field.type.__module__ == "vmlinux": |
| 236 | + size_of_field: int = 0 |
| 237 | + if processing_field.ctype_complex_type is not None: |
| 238 | + if issubclass(processing_field.ctype_complex_type, ctypes.Array): |
| 239 | + if processing_field.containing_type.__module__ == ctypes.__name__: |
| 240 | + size_of_field = ( |
| 241 | + ctypes.sizeof(processing_field.containing_type) |
| 242 | + * processing_field.type_size |
| 243 | + ) |
| 244 | + return size_of_field |
| 245 | + elif processing_field.containing_type.__module__ == "vmlinux": |
| 246 | + size_of_field = ( |
| 247 | + size_of_containing_type |
| 248 | + * processing_field.type_size |
| 249 | + ) |
| 250 | + return size_of_field |
| 251 | + elif issubclass(processing_field.ctype_complex_type, ctypes._Pointer): |
| 252 | + return ctypes.sizeof(ctypes.pointer()) |
| 253 | + else: |
| 254 | + raise NotImplementedError( |
| 255 | + "This subclass of ctype not supported yet" |
| 256 | + ) |
| 257 | + else: |
| 258 | + # search up pre-created stuff and get size |
| 259 | + return size_of_containing_type |
| 260 | + |
| 261 | + else: |
| 262 | + raise ModuleNotFoundError("Module is not supported for the operation") |
| 263 | + raise RuntimeError("control should not reach here") |
| 264 | + |
228 | 265 | @property |
229 | 266 | def is_ready(self) -> bool: |
230 | 267 | """Check if the node is ready (all fields are ready).""" |
|
0 commit comments