summaryrefslogtreecommitdiff
path: root/msgpack/fallback.py
diff options
context:
space:
mode:
authorINADA Naoki <inada-n@klab.com>2013-10-21 00:59:22 +0900
committerINADA Naoki <inada-n@klab.com>2013-10-21 00:59:22 +0900
commite3fee4db5fbf1ead4a98fff6c8843574480c3c2a (patch)
tree1cff58d64577660b7d632806a67b798716c37854 /msgpack/fallback.py
parent37c2ad63af8a6e5cb6944f80d931fedbc6b49e7d (diff)
downloadmsgpack-python-e3fee4db5fbf1ead4a98fff6c8843574480c3c2a.tar.gz
fallback: support packing ExtType
Diffstat (limited to 'msgpack/fallback.py')
-rw-r--r--msgpack/fallback.py181
1 files changed, 105 insertions, 76 deletions
diff --git a/msgpack/fallback.py b/msgpack/fallback.py
index 0b29700..bf5b1c2 100644
--- a/msgpack/fallback.py
+++ b/msgpack/fallback.py
@@ -506,82 +506,111 @@ class Packer(object):
self._default = default
def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
- if nest_limit < 0:
- raise PackValueError("recursion limit exceeded")
- if obj is None:
- return self._buffer.write(b"\xc0")
- if isinstance(obj, bool):
- if obj:
- return self._buffer.write(b"\xc3")
- return self._buffer.write(b"\xc2")
- if isinstance(obj, int_types):
- if 0 <= obj < 0x80:
- return self._buffer.write(struct.pack("B", obj))
- if -0x20 <= obj < 0:
- return self._buffer.write(struct.pack("b", obj))
- if 0x80 <= obj <= 0xff:
- return self._buffer.write(struct.pack("BB", 0xcc, obj))
- if -0x80 <= obj < 0:
- return self._buffer.write(struct.pack(">Bb", 0xd0, obj))
- if 0xff < obj <= 0xffff:
- return self._buffer.write(struct.pack(">BH", 0xcd, obj))
- if -0x8000 <= obj < -0x80:
- return self._buffer.write(struct.pack(">Bh", 0xd1, obj))
- if 0xffff < obj <= 0xffffffff:
- return self._buffer.write(struct.pack(">BI", 0xce, obj))
- if -0x80000000 <= obj < -0x8000:
- return self._buffer.write(struct.pack(">Bi", 0xd2, obj))
- if 0xffffffff < obj <= 0xffffffffffffffff:
- return self._buffer.write(struct.pack(">BQ", 0xcf, obj))
- if -0x8000000000000000 <= obj < -0x80000000:
- return self._buffer.write(struct.pack(">Bq", 0xd3, obj))
- raise PackValueError("Integer value out of range")
- if self._use_bin_type and isinstance(obj, bytes):
- n = len(obj)
- if n <= 0xff:
- self._buffer.write(struct.pack('>BB', 0xc4, n))
- elif n <= 0xffff:
- self._buffer.write(struct.pack(">BH", 0xc5, n))
- elif n <= 0xffffffff:
- self._buffer.write(struct.pack(">BI", 0xc6, n))
- else:
- raise PackValueError("Bytes is too large")
- return self._buffer.write(obj)
- if isinstance(obj, (Unicode, bytes)):
- if isinstance(obj, Unicode):
- if self._encoding is None:
- raise TypeError(
- "Can't encode unicode string: "
- "no encoding is specified")
- obj = obj.encode(self._encoding, self._unicode_errors)
- n = len(obj)
- if n <= 0x1f:
- self._buffer.write(struct.pack('B', 0xa0 + n))
- elif self._use_bin_type and n <= 0xff:
- self._buffer.write(struct.pack('>BB', 0xd9, n))
- elif n <= 0xffff:
- self._buffer.write(struct.pack(">BH", 0xda, n))
- elif n <= 0xffffffff:
- self._buffer.write(struct.pack(">BI", 0xdb, n))
- else:
- raise PackValueError("String is too large")
- return self._buffer.write(obj)
- if isinstance(obj, float):
- if self._use_float:
- return self._buffer.write(struct.pack(">Bf", 0xca, obj))
- return self._buffer.write(struct.pack(">Bd", 0xcb, obj))
- if isinstance(obj, (list, tuple)):
- n = len(obj)
- self._fb_pack_array_header(n)
- for i in xrange(n):
- self._pack(obj[i], nest_limit - 1)
- return
- if isinstance(obj, dict):
- return self._fb_pack_map_pairs(len(obj), dict_iteritems(obj),
- nest_limit - 1)
- if self._default is not None:
- return self._pack(self._default(obj), nest_limit - 1)
- raise TypeError("Cannot serialize %r" % obj)
+ default_used = False
+ while True:
+ if nest_limit < 0:
+ raise PackValueError("recursion limit exceeded")
+ if obj is None:
+ return self._buffer.write(b"\xc0")
+ if isinstance(obj, bool):
+ if obj:
+ return self._buffer.write(b"\xc3")
+ return self._buffer.write(b"\xc2")
+ if isinstance(obj, int_types):
+ if 0 <= obj < 0x80:
+ return self._buffer.write(struct.pack("B", obj))
+ if -0x20 <= obj < 0:
+ return self._buffer.write(struct.pack("b", obj))
+ if 0x80 <= obj <= 0xff:
+ return self._buffer.write(struct.pack("BB", 0xcc, obj))
+ if -0x80 <= obj < 0:
+ return self._buffer.write(struct.pack(">Bb", 0xd0, obj))
+ if 0xff < obj <= 0xffff:
+ return self._buffer.write(struct.pack(">BH", 0xcd, obj))
+ if -0x8000 <= obj < -0x80:
+ return self._buffer.write(struct.pack(">Bh", 0xd1, obj))
+ if 0xffff < obj <= 0xffffffff:
+ return self._buffer.write(struct.pack(">BI", 0xce, obj))
+ if -0x80000000 <= obj < -0x8000:
+ return self._buffer.write(struct.pack(">Bi", 0xd2, obj))
+ if 0xffffffff < obj <= 0xffffffffffffffff:
+ return self._buffer.write(struct.pack(">BQ", 0xcf, obj))
+ if -0x8000000000000000 <= obj < -0x80000000:
+ return self._buffer.write(struct.pack(">Bq", 0xd3, obj))
+ raise PackValueError("Integer value out of range")
+ if self._use_bin_type and isinstance(obj, bytes):
+ n = len(obj)
+ if n <= 0xff:
+ self._buffer.write(struct.pack('>BB', 0xc4, n))
+ elif n <= 0xffff:
+ self._buffer.write(struct.pack(">BH", 0xc5, n))
+ elif n <= 0xffffffff:
+ self._buffer.write(struct.pack(">BI", 0xc6, n))
+ else:
+ raise PackValueError("Bytes is too large")
+ return self._buffer.write(obj)
+ if isinstance(obj, (Unicode, bytes)):
+ if isinstance(obj, Unicode):
+ if self._encoding is None:
+ raise TypeError(
+ "Can't encode unicode string: "
+ "no encoding is specified")
+ obj = obj.encode(self._encoding, self._unicode_errors)
+ n = len(obj)
+ if n <= 0x1f:
+ self._buffer.write(struct.pack('B', 0xa0 + n))
+ elif self._use_bin_type and n <= 0xff:
+ self._buffer.write(struct.pack('>BB', 0xd9, n))
+ elif n <= 0xffff:
+ self._buffer.write(struct.pack(">BH", 0xda, n))
+ elif n <= 0xffffffff:
+ self._buffer.write(struct.pack(">BI", 0xdb, n))
+ else:
+ raise PackValueError("String is too large")
+ return self._buffer.write(obj)
+ if isinstance(obj, float):
+ if self._use_float:
+ return self._buffer.write(struct.pack(">Bf", 0xca, obj))
+ return self._buffer.write(struct.pack(">Bd", 0xcb, obj))
+ if isinstance(obj, ExtType):
+ code = obj.code
+ data = obj.data
+ assert isinstance(code, int)
+ assert isinstance(data, bytes)
+ L = len(data)
+ if L == 1:
+ self._buffer.write(b'\xd4')
+ elif L == 2:
+ self._buffer.write(b'\xd5')
+ elif L == 4:
+ self._buffer.write(b'\xd6')
+ elif L == 8:
+ self._buffer.write(b'\xd7')
+ elif L == 16:
+ self._buffer.write(b'\xd8')
+ elif L <= 0xff:
+ self._buffer.write(struct.pack(">BB", 0xc7, L))
+ elif L <= 0xffff:
+ self._buffer.write(struct.pack(">BH", 0xc8, L))
+ else:
+ self._buffer.write(struct.pack(">BI", 0xc9, L))
+ self._buffer.write(struct.pack("b", code))
+ self._buffer.write(data)
+ return
+ if isinstance(obj, (list, tuple)):
+ n = len(obj)
+ self._fb_pack_array_header(n)
+ for i in xrange(n):
+ self._pack(obj[i], nest_limit - 1)
+ return
+ if isinstance(obj, dict):
+ return self._fb_pack_map_pairs(len(obj), dict_iteritems(obj),
+ nest_limit - 1)
+ if not default_used and self._default is not None:
+ obj = self._default(obj)
+ default_used = 1
+ continue
+ raise TypeError("Cannot serialize %r" % obj)
def pack(self, obj):
self._pack(obj)