11from dataclasses import dataclass , field
22from typing import Dict , Any , Optional
3+ import ctypes
34
45
56# TODO: FIX THE FUCKING TYPE NAME CONVENTION.
@@ -13,6 +14,7 @@ class Field:
1314 containing_type : Optional [Any ]
1415 type_size : Optional [int ]
1516 bitfield_size : Optional [int ]
17+ offset : int
1618 value : Any = None
1719 ready : bool = False
1820
@@ -60,6 +62,10 @@ def set_bitfield_size(self, bitfield_size: Any, mark_ready: bool = False) -> Non
6062 if mark_ready :
6163 self .ready = True
6264
65+ def set_offset (self , offset : int ) -> None :
66+ """Set the offset of this field"""
67+ self .offset = offset
68+
6369
6470@dataclass
6571class DependencyNode :
@@ -109,6 +115,7 @@ class DependencyNode:
109115 depends_on : Optional [list [str ]] = None
110116 fields : Dict [str , Field ] = field (default_factory = dict )
111117 _ready_cache : Optional [bool ] = field (default = None , repr = False )
118+ current_offset : int = 0
112119
113120 def add_field (
114121 self ,
@@ -120,6 +127,7 @@ def add_field(
120127 ctype_complex_type : Optional [int ] = None ,
121128 bitfield_size : Optional [int ] = None ,
122129 ready : bool = False ,
130+ offset : int = 0 ,
123131 ) -> None :
124132 """Add a field to the node with an optional initial value and readiness state."""
125133 if self .depends_on is None :
@@ -133,10 +141,14 @@ def add_field(
133141 type_size = type_size ,
134142 ctype_complex_type = ctype_complex_type ,
135143 bitfield_size = bitfield_size ,
144+ offset = offset ,
136145 )
137146 # Invalidate readiness cache
138147 self ._ready_cache = None
139148
149+ def __sizeof__ (self ):
150+ return self .current_offset
151+
140152 def get_field (self , name : str ) -> Field :
141153 """Get a field by name."""
142154 return self .fields [name ]
@@ -203,15 +215,78 @@ def set_field_bitfield_size(
203215 # Invalidate readiness cache
204216 self ._ready_cache = None
205217
206- def set_field_ready (self , name : str , is_ready : bool = False ) -> None :
218+ def set_field_ready (
219+ self ,
220+ name : str ,
221+ is_ready : bool = False ,
222+ size_of_containing_type : Optional [int ] = None ,
223+ ) -> None :
207224 """Mark a field as ready or not ready."""
208225 if name not in self .fields :
209226 raise KeyError (f"Field '{ name } ' does not exist in node '{ self .name } '" )
210227
211228 self .fields [name ].set_ready (is_ready )
229+ self .fields [name ].set_offset (self .current_offset )
230+ self .current_offset += self ._calculate_size (name , size_of_containing_type )
212231 # Invalidate readiness cache
213232 self ._ready_cache = None
214233
234+ def _calculate_size (
235+ self , name : str , size_of_containing_type : Optional [int ] = None
236+ ) -> int :
237+ processing_field = self .fields [name ]
238+ # size_of_field will be in bytes
239+ if processing_field .type .__module__ == ctypes .__name__ :
240+ size_of_field = ctypes .sizeof (processing_field .type )
241+ return size_of_field
242+ elif processing_field .type .__module__ == "vmlinux" :
243+ if processing_field .ctype_complex_type is not None :
244+ if issubclass (processing_field .ctype_complex_type , ctypes .Array ):
245+ if processing_field .containing_type .__module__ == ctypes .__name__ :
246+ if (
247+ processing_field .containing_type is not None
248+ and processing_field .type_size is not None
249+ ):
250+ size_of_field = (
251+ ctypes .sizeof (processing_field .containing_type )
252+ * processing_field .type_size
253+ )
254+ else :
255+ raise RuntimeError (
256+ f"{ processing_field } has no containing_type or type_size"
257+ )
258+ return size_of_field
259+ elif processing_field .containing_type .__module__ == "vmlinux" :
260+ if (
261+ size_of_containing_type is not None
262+ and processing_field .type_size is not None
263+ ):
264+ size_of_field = (
265+ size_of_containing_type * processing_field .type_size
266+ )
267+ else :
268+ raise RuntimeError (
269+ f"{ processing_field } has no containing_type or type_size"
270+ )
271+ return size_of_field
272+ elif issubclass (processing_field .ctype_complex_type , ctypes ._Pointer ):
273+ return ctypes .sizeof (ctypes .c_void_p )
274+ else :
275+ raise NotImplementedError (
276+ "This subclass of ctype not supported yet"
277+ )
278+ else :
279+ # search up pre-created stuff and get size
280+ if size_of_containing_type is None :
281+ raise RuntimeError (
282+ f"Size of containing type { size_of_containing_type } is None"
283+ )
284+ return size_of_containing_type
285+
286+ else :
287+ raise ModuleNotFoundError ("Module is not supported for the operation" )
288+ raise RuntimeError ("control should not reach here" )
289+
215290 @property
216291 def is_ready (self ) -> bool :
217292 """Check if the node is ready (all fields are ready)."""
0 commit comments