def _unpack(self, execute=EX_CONSTRUCT):
        typ, n, obj = self._read_header(execute)

        if execute == EX_READ_ARRAY_HEADER:
            if typ != TYPE_ARRAY:
                raise UnpackValueError("Expected array")
            return n
        if execute == EX_READ_MAP_HEADER:
            if typ != TYPE_MAP:
                raise UnpackValueError("Expected map")
            return n
        # TODO should we eliminate the recursion?
        if typ == TYPE_ARRAY:
            if execute == EX_SKIP:
                for i in range(n):
                    # TODO check whether we need to call `list_hook`
                    self._unpack(EX_SKIP)
                return
            ret = newlist_hint(n)
            for i in range(n):
                ret.append(self._unpack(EX_CONSTRUCT))
            if self._list_hook is not None:
                ret = self._list_hook(ret)
            # TODO is the interaction between `list_hook` and `use_list` ok?
            return ret if self._use_list else tuple(ret)
        if typ == TYPE_MAP:
            if execute == EX_SKIP:
                for i in range(n):
                    # TODO check whether we need to call hooks
                    self._unpack(EX_SKIP)
                    self._unpack(EX_SKIP)
                return
            if self._object_pairs_hook is not None:
                ret = self._object_pairs_hook(
                    (self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT))
                    for _ in range(n))
            else:
                ret = {}
                for _ in range(n):
                    key = self._unpack(EX_CONSTRUCT)
                    ret[key] = self._unpack(EX_CONSTRUCT)
                if self._object_hook is not None:
                    ret = self._object_hook(ret)
            return ret
        if execute == EX_SKIP:
            return
        if typ == TYPE_RAW:
            if self._encoding is not None:
                obj = obj.decode(self._encoding, self._unicode_errors)
            elif self._raw:
                obj = bytes(obj)
            else:
                obj = obj.decode('utf_8')
            return obj
        if typ == TYPE_EXT:
            return self._ext_hook(n, bytes(obj))
        if typ == TYPE_BIN:
            return bytes(obj)
        assert typ == TYPE_IMMEDIATE
        return obj
def unpackb(packed, **kwargs):
    """
    Unpack an object from `packed`.

    Raises `ExtraData` when `packed` contains extra bytes.
    See :class:`Unpacker` for options.
    """
    unpacker = Unpacker(None, **kwargs)
    unpacker.feed(packed)
    try:
        ret = unpacker._unpack()
    except OutOfData:
        raise UnpackValueError("Data is not enough.")
    if unpacker._got_extradata():
        raise ExtraData(ret, unpacker._get_extradata())
    return ret
 def _read_header(self, execute=EX_CONSTRUCT):
     typ = TYPE_IMMEDIATE
     n = 0
     obj = None
     self._reserve(1)
     b = self._buffer[self._buff_i]
     self._buff_i += 1
     if b & 0b10000000 == 0:
         obj = b
     elif b & 0b11100000 == 0b11100000:
         obj = -1 - (b ^ 0xff)
     elif b & 0b11100000 == 0b10100000:
         n = b & 0b00011111
         typ = TYPE_RAW
         if n > self._max_str_len:
             raise UnpackValueError("%s exceeds max_str_len(%s)", n,
                                    self._max_str_len)
         obj = self._read(n)
     elif b & 0b11110000 == 0b10010000:
         n = b & 0b00001111
         typ = TYPE_ARRAY
         if n > self._max_array_len:
             raise UnpackValueError("%s exceeds max_array_len(%s)", n,
                                    self._max_array_len)
     elif b & 0b11110000 == 0b10000000:
         n = b & 0b00001111
         typ = TYPE_MAP
         if n > self._max_map_len:
             raise UnpackValueError("%s exceeds max_map_len(%s)", n,
                                    self._max_map_len)
     elif b == 0xc0:
         obj = None
     elif b == 0xc2:
         obj = False
     elif b == 0xc3:
         obj = True
     elif b == 0xc4:
         typ = TYPE_BIN
         self._reserve(1)
         n = self._buffer[self._buff_i]
         self._buff_i += 1
         if n > self._max_bin_len:
             raise UnpackValueError("%s exceeds max_bin_len(%s)" %
                                    (n, self._max_bin_len))
         obj = self._read(n)
     elif b == 0xc5:
         typ = TYPE_BIN
         self._reserve(2)
         n = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0]
         self._buff_i += 2
         if n > self._max_bin_len:
             raise UnpackValueError("%s exceeds max_bin_len(%s)" %
                                    (n, self._max_bin_len))
         obj = self._read(n)
     elif b == 0xc6:
         typ = TYPE_BIN
         self._reserve(4)
         n = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0]
         self._buff_i += 4
         if n > self._max_bin_len:
             raise UnpackValueError("%s exceeds max_bin_len(%s)" %
                                    (n, self._max_bin_len))
         obj = self._read(n)
     elif b == 0xc7:  # ext 8
         typ = TYPE_EXT
         self._reserve(2)
         L, n = struct.unpack_from('Bb', self._buffer_view, self._buff_i)
         self._buff_i += 2
         if L > self._max_ext_len:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (L, self._max_ext_len))
         obj = self._read(L)
     elif b == 0xc8:  # ext 16
         typ = TYPE_EXT
         self._reserve(3)
         L, n = struct.unpack_from('>Hb', self._buffer_view, self._buff_i)
         self._buff_i += 3
         if L > self._max_ext_len:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (L, self._max_ext_len))
         obj = self._read(L)
     elif b == 0xc9:  # ext 32
         typ = TYPE_EXT
         self._reserve(5)
         L, n = struct.unpack_from('>Ib', self._buffer_view, self._buff_i)
         self._buff_i += 5
         if L > self._max_ext_len:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (L, self._max_ext_len))
         obj = self._read(L)
     elif b == 0xca:
         self._reserve(4)
         obj = struct.unpack_from(">f", self._buffer_view, self._buff_i)[0]
         self._buff_i += 4
     elif b == 0xcb:
         self._reserve(8)
         obj = struct.unpack_from(">d", self._buffer_view, self._buff_i)[0]
         self._buff_i += 8
     elif b == 0xcc:
         self._reserve(1)
         obj = self._buffer[self._buff_i]
         self._buff_i += 1
     elif b == 0xcd:
         self._reserve(2)
         obj = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0]
         self._buff_i += 2
     elif b == 0xce:
         self._reserve(4)
         obj = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0]
         self._buff_i += 4
     elif b == 0xcf:
         self._reserve(8)
         obj = struct.unpack_from(">Q", self._buffer_view, self._buff_i)[0]
         self._buff_i += 8
     elif b == 0xd0:
         self._reserve(1)
         obj = struct.unpack_from("b", self._buffer_view, self._buff_i)[0]
         self._buff_i += 1
     elif b == 0xd1:
         self._reserve(2)
         obj = struct.unpack_from(">h", self._buffer_view, self._buff_i)[0]
         self._buff_i += 2
     elif b == 0xd2:
         self._reserve(4)
         obj = struct.unpack_from(">i", self._buffer_view, self._buff_i)[0]
         self._buff_i += 4
     elif b == 0xd3:
         self._reserve(8)
         obj = struct.unpack_from(">q", self._buffer_view, self._buff_i)[0]
         self._buff_i += 8
     elif b == 0xd4:  # fixext 1
         typ = TYPE_EXT
         if self._max_ext_len < 1:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (1, self._max_ext_len))
         self._reserve(2)
         n, obj = struct.unpack_from("b1s", self._buffer_view, self._buff_i)
         self._buff_i += 2
     elif b == 0xd5:  # fixext 2
         typ = TYPE_EXT
         if self._max_ext_len < 2:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (2, self._max_ext_len))
         self._reserve(3)
         n, obj = struct.unpack_from("b2s", self._buffer_view, self._buff_i)
         self._buff_i += 3
     elif b == 0xd6:  # fixext 4
         typ = TYPE_EXT
         if self._max_ext_len < 4:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (4, self._max_ext_len))
         self._reserve(5)
         n, obj = struct.unpack_from("b4s", self._buffer_view, self._buff_i)
         self._buff_i += 5
     elif b == 0xd7:  # fixext 8
         typ = TYPE_EXT
         if self._max_ext_len < 8:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (8, self._max_ext_len))
         self._reserve(9)
         n, obj = struct.unpack_from("b8s", self._buffer_view, self._buff_i)
         self._buff_i += 9
     elif b == 0xd8:  # fixext 16
         typ = TYPE_EXT
         if self._max_ext_len < 16:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (16, self._max_ext_len))
         self._reserve(17)
         n, obj = struct.unpack_from("b16s", self._buffer_view,
                                     self._buff_i)
         self._buff_i += 17
     elif b == 0xd9:
         typ = TYPE_RAW
         self._reserve(1)
         n = self._buffer[self._buff_i]
         self._buff_i += 1
         if n > self._max_str_len:
             raise UnpackValueError("%s exceeds max_str_len(%s)", n,
                                    self._max_str_len)
         obj = self._read(n)
     elif b == 0xda:
         typ = TYPE_RAW
         self._reserve(2)
         n, = struct.unpack_from(">H", self._buffer_view, self._buff_i)
         self._buff_i += 2
         if n > self._max_str_len:
             raise UnpackValueError("%s exceeds max_str_len(%s)", n,
                                    self._max_str_len)
         obj = self._read(n)
     elif b == 0xdb:
         typ = TYPE_RAW
         self._reserve(4)
         n, = struct.unpack_from(">I", self._buffer_view, self._buff_i)
         self._buff_i += 4
         if n > self._max_str_len:
             raise UnpackValueError("%s exceeds max_str_len(%s)", n,
                                    self._max_str_len)
         obj = self._read(n)
     elif b == 0xdc:
         typ = TYPE_ARRAY
         self._reserve(2)
         n, = struct.unpack_from(">H", self._buffer_view, self._buff_i)
         self._buff_i += 2
         if n > self._max_array_len:
             raise UnpackValueError("%s exceeds max_array_len(%s)", n,
                                    self._max_array_len)
     elif b == 0xdd:
         typ = TYPE_ARRAY
         self._reserve(4)
         n, = struct.unpack_from(">I", self._buffer_view, self._buff_i)
         self._buff_i += 4
         if n > self._max_array_len:
             raise UnpackValueError("%s exceeds max_array_len(%s)", n,
                                    self._max_array_len)
     elif b == 0xde:
         self._reserve(2)
         n, = struct.unpack_from(">H", self._buffer_view, self._buff_i)
         self._buff_i += 2
         if n > self._max_map_len:
             raise UnpackValueError("%s exceeds max_map_len(%s)", n,
                                    self._max_map_len)
         typ = TYPE_MAP
     elif b == 0xdf:
         self._reserve(4)
         n, = struct.unpack_from(">I", self._buffer_view, self._buff_i)
         self._buff_i += 4
         if n > self._max_map_len:
             raise UnpackValueError("%s exceeds max_map_len(%s)", n,
                                    self._max_map_len)
         typ = TYPE_MAP
     else:
         raise UnpackValueError("Unknown header: 0x%x" % b)
     return typ, n, obj
Exemple #4
0
 def _read_header(self, execute=EX_CONSTRUCT):
     typ = TYPE_IMMEDIATE
     n = 0
     obj = None
     self._reserve(1)
     b = self._buffer[self._buff_i]
     self._buff_i += 1
     if b & 0b10000000 == 0:
         obj = b
     elif b & 0b11100000 == 0b11100000:
         obj = -1 - (b ^ 0xFF)
     elif b & 0b11100000 == 0b10100000:
         n = b & 0b00011111
         typ = TYPE_RAW
         if n > self._max_str_len:
             raise UnpackValueError("%s exceeds max_str_len(%s)", n,
                                    self._max_str_len)
         obj = self._read(n)
     elif b & 0b11110000 == 0b10010000:
         n = b & 0b00001111
         typ = TYPE_ARRAY
         if n > self._max_array_len:
             raise UnpackValueError("%s exceeds max_array_len(%s)", n,
                                    self._max_array_len)
     elif b & 0b11110000 == 0b10000000:
         n = b & 0b00001111
         typ = TYPE_MAP
         if n > self._max_map_len:
             raise UnpackValueError("%s exceeds max_map_len(%s)", n,
                                    self._max_map_len)
     elif b == 0xC0:
         obj = None
     elif b == 0xC2:
         obj = False
     elif b == 0xC3:
         obj = True
     elif b == 0xC4:
         typ = TYPE_BIN
         self._reserve(1)
         n = self._buffer[self._buff_i]
         self._buff_i += 1
         if n > self._max_bin_len:
             raise UnpackValueError("%s exceeds max_bin_len(%s)" %
                                    (n, self._max_bin_len))
         obj = self._read(n)
     elif b == 0xC5:
         typ = TYPE_BIN
         self._reserve(2)
         n = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0]
         self._buff_i += 2
         if n > self._max_bin_len:
             raise UnpackValueError("%s exceeds max_bin_len(%s)" %
                                    (n, self._max_bin_len))
         obj = self._read(n)
     elif b == 0xC6:
         typ = TYPE_BIN
         self._reserve(4)
         n = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0]
         self._buff_i += 4
         if n > self._max_bin_len:
             raise UnpackValueError("%s exceeds max_bin_len(%s)" %
                                    (n, self._max_bin_len))
         obj = self._read(n)
     elif b == 0xC7:  # ext 8
         typ = TYPE_EXT
         self._reserve(2)
         L, n = struct.unpack_from("Bb", self._buffer_view, self._buff_i)
         self._buff_i += 2
         if L > self._max_ext_len:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (L, self._max_ext_len))
         obj = self._read(L)
     elif b == 0xC8:  # ext 16
         typ = TYPE_EXT
         self._reserve(3)
         L, n = struct.unpack_from(">Hb", self._buffer_view, self._buff_i)
         self._buff_i += 3
         if L > self._max_ext_len:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (L, self._max_ext_len))
         obj = self._read(L)
     elif b == 0xC9:  # ext 32
         typ = TYPE_EXT
         self._reserve(5)
         L, n = struct.unpack_from(">Ib", self._buffer_view, self._buff_i)
         self._buff_i += 5
         if L > self._max_ext_len:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (L, self._max_ext_len))
         obj = self._read(L)
     elif b == 0xCA:
         self._reserve(4)
         obj = struct.unpack_from(">f", self._buffer_view, self._buff_i)[0]
         self._buff_i += 4
     elif b == 0xCB:
         self._reserve(8)
         obj = struct.unpack_from(">d", self._buffer_view, self._buff_i)[0]
         self._buff_i += 8
     elif b == 0xCC:
         self._reserve(1)
         obj = self._buffer[self._buff_i]
         self._buff_i += 1
     elif b == 0xCD:
         self._reserve(2)
         obj = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0]
         self._buff_i += 2
     elif b == 0xCE:
         self._reserve(4)
         obj = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0]
         self._buff_i += 4
     elif b == 0xCF:
         self._reserve(8)
         obj = struct.unpack_from(">Q", self._buffer_view, self._buff_i)[0]
         self._buff_i += 8
     elif b == 0xD0:
         self._reserve(1)
         obj = struct.unpack_from("b", self._buffer_view, self._buff_i)[0]
         self._buff_i += 1
     elif b == 0xD1:
         self._reserve(2)
         obj = struct.unpack_from(">h", self._buffer_view, self._buff_i)[0]
         self._buff_i += 2
     elif b == 0xD2:
         self._reserve(4)
         obj = struct.unpack_from(">i", self._buffer_view, self._buff_i)[0]
         self._buff_i += 4
     elif b == 0xD3:
         self._reserve(8)
         obj = struct.unpack_from(">q", self._buffer_view, self._buff_i)[0]
         self._buff_i += 8
     elif b == 0xD4:  # fixext 1
         typ = TYPE_EXT
         if self._max_ext_len < 1:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (1, self._max_ext_len))
         self._reserve(2)
         n, obj = struct.unpack_from("b1s", self._buffer_view, self._buff_i)
         self._buff_i += 2
     elif b == 0xD5:  # fixext 2
         typ = TYPE_EXT
         if self._max_ext_len < 2:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (2, self._max_ext_len))
         self._reserve(3)
         n, obj = struct.unpack_from("b2s", self._buffer_view, self._buff_i)
         self._buff_i += 3
     elif b == 0xD6:  # fixext 4
         typ = TYPE_EXT
         if self._max_ext_len < 4:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (4, self._max_ext_len))
         self._reserve(5)
         n, obj = struct.unpack_from("b4s", self._buffer_view, self._buff_i)
         self._buff_i += 5
     elif b == 0xD7:  # fixext 8
         typ = TYPE_EXT
         if self._max_ext_len < 8:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (8, self._max_ext_len))
         self._reserve(9)
         n, obj = struct.unpack_from("b8s", self._buffer_view, self._buff_i)
         self._buff_i += 9
     elif b == 0xD8:  # fixext 16
         typ = TYPE_EXT
         if self._max_ext_len < 16:
             raise UnpackValueError("%s exceeds max_ext_len(%s)" %
                                    (16, self._max_ext_len))
         self._reserve(17)
         n, obj = struct.unpack_from("b16s", self._buffer_view,
                                     self._buff_i)
         self._buff_i += 17
     elif b == 0xD9:
         typ = TYPE_RAW
         self._reserve(1)
         n = self._buffer[self._buff_i]
         self._buff_i += 1
         if n > self._max_str_len:
             raise UnpackValueError("%s exceeds max_str_len(%s)", n,
                                    self._max_str_len)
         obj = self._read(n)
     elif b == 0xDA:
         typ = TYPE_RAW
         self._reserve(2)
         n, = struct.unpack_from(">H", self._buffer_view, self._buff_i)
         self._buff_i += 2
         if n > self._max_str_len:
             raise UnpackValueError("%s exceeds max_str_len(%s)", n,
                                    self._max_str_len)
         obj = self._read(n)
     elif b == 0xDB:
         typ = TYPE_RAW
         self._reserve(4)
         n, = struct.unpack_from(">I", self._buffer_view, self._buff_i)
         self._buff_i += 4
         if n > self._max_str_len:
             raise UnpackValueError("%s exceeds max_str_len(%s)", n,
                                    self._max_str_len)
         obj = self._read(n)
     elif b == 0xDC:
         typ = TYPE_ARRAY
         self._reserve(2)
         n, = struct.unpack_from(">H", self._buffer_view, self._buff_i)
         self._buff_i += 2
         if n > self._max_array_len:
             raise UnpackValueError("%s exceeds max_array_len(%s)", n,
                                    self._max_array_len)
     elif b == 0xDD:
         typ = TYPE_ARRAY
         self._reserve(4)
         n, = struct.unpack_from(">I", self._buffer_view, self._buff_i)
         self._buff_i += 4
         if n > self._max_array_len:
             raise UnpackValueError("%s exceeds max_array_len(%s)", n,
                                    self._max_array_len)
     elif b == 0xDE:
         self._reserve(2)
         n, = struct.unpack_from(">H", self._buffer_view, self._buff_i)
         self._buff_i += 2
         if n > self._max_map_len:
             raise UnpackValueError("%s exceeds max_map_len(%s)", n,
                                    self._max_map_len)
         typ = TYPE_MAP
     elif b == 0xDF:
         self._reserve(4)
         n, = struct.unpack_from(">I", self._buffer_view, self._buff_i)
         self._buff_i += 4
         if n > self._max_map_len:
             raise UnpackValueError("%s exceeds max_map_len(%s)", n,
                                    self._max_map_len)
         typ = TYPE_MAP
     else:
         raise UnpackValueError("Unknown header: 0x%x" % b)
     return typ, n, obj
Exemple #5
0
 def _read_header(self, execute=EX_CONSTRUCT, write_bytes=None):
     typ = TYPE_IMMEDIATE
     n = 0
     obj = None
     c = self._fb_read(1, write_bytes)
     b = ord(c)
     if b & 0b10000000 == 0:
         obj = b
     elif b & 0b11100000 == 0b11100000:
         obj = struct.unpack("b", c)[0]
     elif b & 0b11100000 == 0b10100000:
         n = b & 0b00011111
         obj = self._fb_read(n, write_bytes)
         typ = TYPE_RAW
         if n > self._max_str_len:
             raise ValueError("%s exceeds max_str_len(%s)", n,
                              self._max_str_len)
     elif b & 0b11110000 == 0b10010000:
         n = b & 0b00001111
         typ = TYPE_ARRAY
         if n > self._max_array_len:
             raise ValueError("%s exceeds max_array_len(%s)", n,
                              self._max_array_len)
     elif b & 0b11110000 == 0b10000000:
         n = b & 0b00001111
         typ = TYPE_MAP
         if n > self._max_map_len:
             raise ValueError("%s exceeds max_map_len(%s)", n,
                              self._max_map_len)
     elif b == 0xc0:
         obj = None
     elif b == 0xc2:
         obj = False
     elif b == 0xc3:
         obj = True
     elif b == 0xc4:
         typ = TYPE_BIN
         n = struct.unpack("B", self._fb_read(1, write_bytes))[0]
         if n > self._max_bin_len:
             raise ValueError("%s exceeds max_bin_len(%s)" %
                              (n, self._max_bin_len))
         obj = self._fb_read(n, write_bytes)
     elif b == 0xc5:
         typ = TYPE_BIN
         n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
         if n > self._max_bin_len:
             raise ValueError("%s exceeds max_bin_len(%s)" %
                              (n, self._max_bin_len))
         obj = self._fb_read(n, write_bytes)
     elif b == 0xc6:
         typ = TYPE_BIN
         n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
         if n > self._max_bin_len:
             raise ValueError("%s exceeds max_bin_len(%s)" %
                              (n, self._max_bin_len))
         obj = self._fb_read(n, write_bytes)
     elif b == 0xc7:  # ext 8
         typ = TYPE_EXT
         L, n = struct.unpack('Bb', self._fb_read(2, write_bytes))
         if L > self._max_ext_len:
             raise ValueError("%s exceeds max_ext_len(%s)" %
                              (L, self._max_ext_len))
         obj = self._fb_read(L, write_bytes)
     elif b == 0xc8:  # ext 16
         typ = TYPE_EXT
         L, n = struct.unpack('>Hb', self._fb_read(3, write_bytes))
         if L > self._max_ext_len:
             raise ValueError("%s exceeds max_ext_len(%s)" %
                              (L, self._max_ext_len))
         obj = self._fb_read(L, write_bytes)
     elif b == 0xc9:  # ext 32
         typ = TYPE_EXT
         L, n = struct.unpack('>Ib', self._fb_read(5, write_bytes))
         if L > self._max_ext_len:
             raise ValueError("%s exceeds max_ext_len(%s)" %
                              (L, self._max_ext_len))
         obj = self._fb_read(L, write_bytes)
     elif b == 0xca:
         obj = struct.unpack(">f", self._fb_read(4, write_bytes))[0]
     elif b == 0xcb:
         obj = struct.unpack(">d", self._fb_read(8, write_bytes))[0]
     elif b == 0xcc:
         obj = struct.unpack("B", self._fb_read(1, write_bytes))[0]
     elif b == 0xcd:
         obj = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
     elif b == 0xce:
         obj = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
     elif b == 0xcf:
         obj = struct.unpack(">Q", self._fb_read(8, write_bytes))[0]
     elif b == 0xd0:
         obj = struct.unpack("b", self._fb_read(1, write_bytes))[0]
     elif b == 0xd1:
         obj = struct.unpack(">h", self._fb_read(2, write_bytes))[0]
     elif b == 0xd2:
         obj = struct.unpack(">i", self._fb_read(4, write_bytes))[0]
     elif b == 0xd3:
         obj = struct.unpack(">q", self._fb_read(8, write_bytes))[0]
     elif b == 0xd4:  # fixext 1
         typ = TYPE_EXT
         if self._max_ext_len < 1:
             raise ValueError("%s exceeds max_ext_len(%s)" %
                              (1, self._max_ext_len))
         n, obj = struct.unpack('b1s', self._fb_read(2, write_bytes))
     elif b == 0xd5:  # fixext 2
         typ = TYPE_EXT
         if self._max_ext_len < 2:
             raise ValueError("%s exceeds max_ext_len(%s)" %
                              (2, self._max_ext_len))
         n, obj = struct.unpack('b2s', self._fb_read(3, write_bytes))
     elif b == 0xd6:  # fixext 4
         typ = TYPE_EXT
         if self._max_ext_len < 4:
             raise ValueError("%s exceeds max_ext_len(%s)" %
                              (4, self._max_ext_len))
         n, obj = struct.unpack('b4s', self._fb_read(5, write_bytes))
     elif b == 0xd7:  # fixext 8
         typ = TYPE_EXT
         if self._max_ext_len < 8:
             raise ValueError("%s exceeds max_ext_len(%s)" %
                              (8, self._max_ext_len))
         n, obj = struct.unpack('b8s', self._fb_read(9, write_bytes))
     elif b == 0xd8:  # fixext 16
         typ = TYPE_EXT
         if self._max_ext_len < 16:
             raise ValueError("%s exceeds max_ext_len(%s)" %
                              (16, self._max_ext_len))
         n, obj = struct.unpack('b16s', self._fb_read(17, write_bytes))
     elif b == 0xd9:
         typ = TYPE_RAW
         n = struct.unpack("B", self._fb_read(1, write_bytes))[0]
         if n > self._max_str_len:
             raise ValueError("%s exceeds max_str_len(%s)", n,
                              self._max_str_len)
         obj = self._fb_read(n, write_bytes)
     elif b == 0xda:
         typ = TYPE_RAW
         n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
         if n > self._max_str_len:
             raise ValueError("%s exceeds max_str_len(%s)", n,
                              self._max_str_len)
         obj = self._fb_read(n, write_bytes)
     elif b == 0xdb:
         typ = TYPE_RAW
         n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
         if n > self._max_str_len:
             raise ValueError("%s exceeds max_str_len(%s)", n,
                              self._max_str_len)
         obj = self._fb_read(n, write_bytes)
     elif b == 0xdc:
         n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
         if n > self._max_array_len:
             raise ValueError("%s exceeds max_array_len(%s)", n,
                              self._max_array_len)
         typ = TYPE_ARRAY
     elif b == 0xdd:
         n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
         if n > self._max_array_len:
             raise ValueError("%s exceeds max_array_len(%s)", n,
                              self._max_array_len)
         typ = TYPE_ARRAY
     elif b == 0xde:
         n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
         if n > self._max_map_len:
             raise ValueError("%s exceeds max_map_len(%s)", n,
                              self._max_map_len)
         typ = TYPE_MAP
     elif b == 0xdf:
         n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
         if n > self._max_map_len:
             raise ValueError("%s exceeds max_map_len(%s)", n,
                              self._max_map_len)
         typ = TYPE_MAP
     else:
         raise UnpackValueError("Unknown header: 0x%x" % b)
     return typ, n, obj