21
21
Iterable ,
22
22
List ,
23
23
Optional ,
24
+ Sequence ,
24
25
Set ,
25
26
Type ,
26
27
TypeVar ,
46
47
CBORTag ,
47
48
FrozenDict ,
48
49
dumps ,
49
- loads ,
50
50
undefined ,
51
51
)
52
52
from frozenlist import FrozenList
@@ -199,6 +199,22 @@ def wrapper(cls, value: Primitive):
199
199
CBORBase = TypeVar ("CBORBase" , bound = "CBORSerializable" )
200
200
201
201
202
+ def decode_array (self , subtype : int ) -> Sequence [Any ]:
203
+ # Major tag 4
204
+ length = self ._decode_length (subtype , allow_indefinite = True )
205
+
206
+ if length is None :
207
+ return IndefiniteList (cast (Primitive , self .decode_array (subtype = subtype )))
208
+ else :
209
+ return self .decode_array (subtype = subtype )
210
+
211
+
212
+ try :
213
+ cbor2 ._decoder .major_decoders [4 ] = decode_array
214
+ except Exception as e :
215
+ logger .warning ("Failed to replace major decoder for indefinite array" , e )
216
+
217
+
202
218
def default_encoder (
203
219
encoder : CBOREncoder , value : Union [CBORSerializable , IndefiniteList ]
204
220
):
@@ -265,7 +281,7 @@ class CBORSerializable:
265
281
does not refer to itself, which could cause infinite loops.
266
282
"""
267
283
268
- def to_shallow_primitive (self ) -> Primitive :
284
+ def to_shallow_primitive (self ) -> Union [ Primitive , CBORSerializable ] :
269
285
"""
270
286
Convert the instance to a CBOR primitive. If the primitive is a container, e.g. list, dict, the type of
271
287
its elements could be either a Primitive or a CBORSerializable.
@@ -516,7 +532,11 @@ def from_cbor(cls, payload: Union[str, bytes]) -> CBORSerializable:
516
532
"""
517
533
if type (payload ) is str :
518
534
payload = bytes .fromhex (payload )
519
- value = loads (payload ) # type: ignore
535
+
536
+ assert isinstance (payload , bytes )
537
+
538
+ value = cbor2 .loads (payload )
539
+
520
540
return cls .from_primitive (value )
521
541
522
542
def __repr__ (self ):
@@ -538,7 +558,7 @@ def _restore_dataclass_field(
538
558
539
559
if "object_hook" in f .metadata :
540
560
return f .metadata ["object_hook" ](v )
541
- return _restore_typed_primitive (f .type , v )
561
+ return _restore_typed_primitive (cast ( Any , f .type ) , v )
542
562
543
563
544
564
def _restore_typed_primitive (
@@ -580,10 +600,14 @@ def _restore_typed_primitive(
580
600
raise DeserializeException (
581
601
f"List types need exactly one type argument, but got { t_args } "
582
602
)
583
- t = t_args [0 ]
584
- if not isinstance (v , list ):
603
+ t_subtype = t_args [0 ]
604
+ if not isinstance (v , ( list , IndefiniteList ) ):
585
605
raise DeserializeException (f"Expected type list but got { type (v )} " )
586
- return IndefiniteList ([_restore_typed_primitive (t , w ) for w in v ])
606
+ v_list = [_restore_typed_primitive (t_subtype , w ) for w in v ]
607
+ if t == IndefiniteList :
608
+ return IndefiniteList (v_list )
609
+ else :
610
+ return v_list
587
611
elif isclass (t ) and t == ByteString :
588
612
if not isinstance (v , bytes ):
589
613
raise DeserializeException (f"Expected type bytes but got { type (v )} " )
@@ -712,8 +736,10 @@ def to_shallow_primitive(self) -> Primitive:
712
736
return primitives
713
737
714
738
@classmethod
715
- @limit_primitive_type (list , tuple )
716
- def from_primitive (cls : Type [ArrayBase ], values : Union [list , tuple ]) -> ArrayBase :
739
+ @limit_primitive_type (list , tuple , IndefiniteList )
740
+ def from_primitive (
741
+ cls : Type [ArrayBase ], values : Union [list , tuple , IndefiniteList ]
742
+ ) -> ArrayBase :
717
743
"""Restore a primitive value to its original class type.
718
744
719
745
Args:
0 commit comments