1717import ctypes
1818import decimal
1919from datetime import date , datetime , timedelta
20- from typing import Any , Tuple , Union
20+ from typing import Any , Tuple , Union , Callable
2121import uuid
2222
2323import attr
@@ -111,6 +111,20 @@ def tc_map(key: bytes, _memo_map: dict = {}):
111111 return _memo_map [key ]
112112
113113
114+ class Conditional :
115+
116+ def __init__ (self , predicate1 : Callable [[any ], bool ], predicate2 : Callable [[any ], bool ], var1 , var2 ):
117+ self .predicate1 = predicate1
118+ self .predicate2 = predicate2
119+ self .var1 = var1
120+ self .var2 = var2
121+
122+ def parse (self , client : 'Client' , context ):
123+ return self .var1 .parse (client ) if self .predicate1 (context ) else self .var2 .parse (client )
124+
125+ def to_python (self , ctype_object , context , * args , ** kwargs ):
126+ return self .var1 .to_python (ctype_object , * args , ** kwargs ) if self .predicate2 (context ) else self .var2 .to_python (ctype_object , * args , ** kwargs )
127+
114128@attr .s
115129class StructArray :
116130 """ `counter_type` counter, followed by count*following structure. """
@@ -193,13 +207,17 @@ def parse(
193207 ) -> Tuple [ctypes .LittleEndianStructure , bytes ]:
194208 buffer = b''
195209 fields = []
210+ values = {}
196211
197212 for name , c_type in self .fields :
198- c_type , buffer_fragment = c_type .parse (client )
213+ is_cond = isinstance (c_type , Conditional )
214+ c_type , buffer_fragment = c_type .parse (client , values ) if is_cond else c_type .parse (client )
199215 buffer += buffer_fragment
200216
201217 fields .append ((name , c_type ))
202218
219+ values [name ] = buffer_fragment
220+
203221 data_class = type (
204222 'StructLE' ,
205223 (ctypes .LittleEndianStructure ,),
@@ -216,7 +234,12 @@ def to_python(
216234 ) -> Union [dict , OrderedDict ]:
217235 result = self .dict_type ()
218236 for name , c_type in self .fields :
237+ is_cond = isinstance (c_type , Conditional )
219238 result [name ] = c_type .to_python (
239+ getattr (ctype_object , name ),
240+ result ,
241+ * args , ** kwargs
242+ ) if is_cond else c_type .to_python (
220243 getattr (ctype_object , name ),
221244 * args , ** kwargs
222245 )
0 commit comments