@@ -58,54 +58,9 @@ def getvalue(self):
5858TYPE_MAP = 2
5959TYPE_RAW = 3
6060
61- DEFAULT_RECURSE_LIMIT = 511
62-
63- def pack (o , stream , ** kwargs ):
64- """
65- Pack object `o` and write it to `stream`
66-
67- See :class:`Packer` for options.
68- """
69- packer = Packer (** kwargs )
70- stream .write (packer .pack (o ))
71-
72- def packb (o , ** kwargs ):
73- """
74- Pack object `o` and return packed bytes
61+ EXTENDED_TYPE = 1000
7562
76- See :class:`Packer` for options.
77- """
78- return Packer (** kwargs ).pack (o )
79-
80- def unpack (stream , ** kwargs ):
81- """
82- Unpack an object from `stream`.
83-
84- Raises `ExtraData` when `packed` contains extra bytes.
85- See :class:`Unpacker` for options.
86- """
87- unpacker = Unpacker (stream , ** kwargs )
88- ret = unpacker ._fb_unpack ()
89- if unpacker ._fb_got_extradata ():
90- raise ExtraData (ret , unpacker ._fb_get_extradata ())
91- return ret
92-
93- def unpackb (packed , ** kwargs ):
94- """
95- Unpack an object from `packed`.
96-
97- Raises `ExtraData` when `packed` contains extra bytes.
98- See :class:`Unpacker` for options.
99- """
100- unpacker = Unpacker (None , ** kwargs )
101- unpacker .feed (packed )
102- try :
103- ret = unpacker ._fb_unpack ()
104- except OutOfData :
105- raise UnpackValueError ("Data is not enough." )
106- if unpacker ._fb_got_extradata ():
107- raise ExtraData (ret , unpacker ._fb_get_extradata ())
108- return ret
63+ DEFAULT_RECURSE_LIMIT = 511
10964
11065class Unpacker (object ):
11166 """
@@ -334,6 +289,9 @@ def _read_header(self, execute=EX_CONSTRUCT, write_bytes=None):
334289 elif b == 0xdf :
335290 n = struct .unpack (">I" , self ._fb_read (4 , write_bytes ))[0 ]
336291 typ = TYPE_MAP
292+ elif b == 0xc9 :
293+ n , typ = struct .unpack (">Ib" , self ._fb_read (5 , write_bytes ))
294+ typ += EXTENDED_TYPE
337295 else :
338296 raise UnpackValueError ("Unknown header: 0x%x" % b )
339297 return typ , n , obj
@@ -390,6 +348,10 @@ def _fb_unpack(self, execute=EX_CONSTRUCT, write_bytes=None):
390348 if self ._encoding is not None :
391349 obj = obj .decode (self ._encoding , self ._unicode_errors )
392350 return obj
351+ if typ >= EXTENDED_TYPE :
352+ typ -= EXTENDED_TYPE
353+ data = self ._fb_read (n , write_bytes )
354+ return self .handle_extended_type (typ , data )
393355 assert typ == TYPE_IMMEDIATE
394356 return obj
395357
@@ -411,6 +373,9 @@ def unpack(self, write_bytes=None):
411373 self ._fb_consume ()
412374 return ret
413375
376+ def handle_extended_type (self , typecode , data ):
377+ raise NotImplementedError ("Cannot decode extended type with typecode=%d" % typecode )
378+
414379 def read_array_header (self , write_bytes = None ):
415380 ret = self ._fb_unpack (EX_READ_ARRAY_HEADER , write_bytes )
416381 self ._fb_consume ()
@@ -521,10 +486,33 @@ def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
521486 if isinstance (obj , dict ):
522487 return self ._fb_pack_map_pairs (len (obj ), dict_iteritems (obj ),
523488 nest_limit - 1 )
489+ if self .pack_extended_type (obj ):
490+ # it means that obj was succesfully handled by
491+ # handle_extended_type, so we are done
492+ return
524493 if self ._default is not None :
525494 return self ._pack (self ._default (obj ), nest_limit - 1 )
526495 raise TypeError ("Cannot serialize %r" % obj )
527496
497+ def pack_extended_type (self , obj ):
498+ res = self .handle_extended_type (obj )
499+ if res is None :
500+ return False
501+ fmt , typecode , data = res
502+ # for now we support only this. We should add support for the other
503+ # fixext/ext formats
504+ assert fmt == "ext 32"
505+ assert 0 <= typecode <= 127
506+ N = len (data )
507+ self ._buffer .write (struct .pack ('>BIB' , 0xc9 , N , typecode ))
508+ self ._buffer .write (data )
509+ return True
510+
511+ def handle_extended_type (self , obj ):
512+ # by default we don't support any extended type. This can be
513+ # overridden by subclasses
514+ return None
515+
528516 def pack (self , obj ):
529517 self ._pack (obj )
530518 ret = self ._buffer .getvalue ()
@@ -590,3 +578,52 @@ def bytes(self):
590578
591579 def reset (self ):
592580 self ._buffer = StringIO ()
581+
582+
583+ def pack (o , stream , Packer = Packer , ** kwargs ):
584+ """
585+ Pack object `o` and write it to `stream`
586+
587+ See :class:`Packer` for options.
588+ """
589+ packer = Packer (** kwargs )
590+ stream .write (packer .pack (o ))
591+
592+ def packb (o , Packer = Packer , ** kwargs ):
593+ """
594+ Pack object `o` and return packed bytes
595+
596+ See :class:`Packer` for options.
597+ """
598+ return Packer (** kwargs ).pack (o )
599+
600+ def unpack (stream , Unpacker = Unpacker , ** kwargs ):
601+ """
602+ Unpack an object from `stream`.
603+
604+ Raises `ExtraData` when `packed` contains extra bytes.
605+ See :class:`Unpacker` for options.
606+ """
607+ unpacker = Unpacker (stream , ** kwargs )
608+ ret = unpacker ._fb_unpack ()
609+ if unpacker ._fb_got_extradata ():
610+ raise ExtraData (ret , unpacker ._fb_get_extradata ())
611+ return ret
612+
613+ def unpackb (packed , Unpacker = Unpacker , ** kwargs ):
614+ """
615+ Unpack an object from `packed`.
616+
617+ Raises `ExtraData` when `packed` contains extra bytes.
618+ See :class:`Unpacker` for options.
619+ """
620+ unpacker = Unpacker (None , ** kwargs )
621+ unpacker .feed (packed )
622+ try :
623+ ret = unpacker ._fb_unpack ()
624+ except OutOfData :
625+ raise UnpackValueError ("Data is not enough." )
626+ if unpacker ._fb_got_extradata ():
627+ raise ExtraData (ret , unpacker ._fb_get_extradata ())
628+ return ret
629+
0 commit comments