Example #1
0
 def deserialize(cls: Type[V], stream: BinaryIO, scope: int) -> V:
     if scope < 1:
         raise Exception("cannot have empty scope for bitlist, need at least a delimiting bit")
     if scope > cls.max_byte_length():
         raise Exception(f"scope is too large: {scope}, max bitlist byte length is: {cls.max_byte_length()}")
     chunks: PyList[Node] = []
     bytelen = scope - 1  # excluding the last byte (which contains the delimiting bit)
     while scope > 32:
         chunks.append(RootNode(Root(stream.read(32))))
         scope -= 32
     # scope is [1, 32] here
     last_chunk_part = stream.read(scope)
     last_byte = int(last_chunk_part[scope-1])
     if last_byte == 0:
         raise Exception("last byte must not be 0: bitlist requires delimiting bit")
     last_byte_bitlen = last_byte.bit_length() - 1  # excluding the delimiting bit
     bitlen = bytelen * 8 + last_byte_bitlen
     if bitlen % 256 != 0:
         last_chunk = last_chunk_part[:scope-1] +\
                      (last_byte ^ (1 << last_byte_bitlen)).to_bytes(length=1, byteorder='little')
         last_chunk += b"\x00" * (32 - len(last_chunk))
         chunks.append(RootNode(Root(last_chunk)))
     if bitlen > cls.limit():
         raise Exception(f"bitlist too long: {bitlen}, delimiting bit is over limit ({cls.limit()})")
     contents = subtree_fill_to_contents(chunks, cls.contents_depth())
     backing = PairNode(contents, uint256(bitlen).get_backing())
     return cast(Bitlist, cls.view_from_backing(backing))
Example #2
0
 def get_backing(self) -> Node:
     if len(self) == 32:  # super common case, optimize for it
         return RootNode(Root(self))
     elif len(self) < 32:
         return RootNode(Root(self + b"\x00" * (32 - len(self))))
     else:
         return subtree_fill_to_contents(pack_bytes_to_chunks(self), self.__class__.tree_depth())
Example #3
0
def pack_bytes_to_chunks(bytez: bytes) -> PyList[Node]:
    full_chunks_byte_len = (len(bytez) >> 5) << 5
    out: PyList[Node] = [
        RootNode(Root(bytez[i:i + 32]))
        for i in range(0, full_chunks_byte_len, 32)
    ]
    if len(bytez) != full_chunks_byte_len:
        out.append(
            RootNode(
                Root(bytez[full_chunks_byte_len:] +
                     (b"\x00" * (32 - (len(bytez) - full_chunks_byte_len))))))
    return out
Example #4
0
def _new_chunk_with_bit(chunk: Node, i: int, v: boolean) -> Node:
    new_chunk_root = bytearray(bytes(chunk.root))  # mutable copy
    if v:
        new_chunk_root[(i & 0xff) >> 3] |= 1 << (i & 0x7)
    else:
        new_chunk_root[(i & 0xff) >> 3] &= (~(1 << (i & 0x7))) & 0xff
    return RootNode(Root(new_chunk_root))
Example #5
0
 def __iter__(self):
     self.i = 0
     self.j = self.per_node
     self.rootIndex = 0
     self.currentRoot = RootNode(ZERO_ROOT)
     self.stack = [None] * self.depth
     return self
Example #6
0
 def deserialize(cls: Type[V], stream: BinaryIO, scope: int) -> V:
     if scope != cls.type_byte_length():
         raise Exception(f"scope is invalid: {scope}, bitvector byte length is: {cls.type_byte_length()}")
     chunks: PyList[Node] = []
     bytelen = scope - 1  # excluding the last byte
     while scope > 32:
         chunks.append(RootNode(Root(stream.read(32))))
         scope -= 32
     # scope is [1, 32] here
     last_chunk_part = stream.read(scope)
     last_byte = int(last_chunk_part[scope-1])
     bitlen = bytelen * 8 + last_byte.bit_length()
     if bitlen > cls.vector_length():
         raise Exception(f"bitvector too long: {bitlen}, last byte has bits over bit length ({cls.vector_length()})")
     last_chunk = last_chunk_part + (b"\x00" * (32 - len(last_chunk_part)))
     chunks.append(RootNode(Root(last_chunk)))
     backing = subtree_fill_to_contents(chunks, cls.tree_depth())
     return cast(Bitvector, cls.view_from_backing(backing))
Example #7
0
def pack_ints_to_chunks(items: Iterable[int],
                        items_per_chunk: int) -> PyList[Node]:
    item_byte_len = 32 // items_per_chunk
    return [
        RootNode(
            Root(b"".join(
                v.to_bytes(length=item_byte_len, byteorder='little')
                for v in chunk_elems)))
        for chunk_elems in grouper(items, items_per_chunk, fillvalue=0)
    ]
Example #8
0
    def __init__(self, anchor: Node, depth: int, length: int):
        self.anchor = anchor
        self.depth = depth
        self.length = length
        self.i = 0
        self.currentRoot = RootNode(ZERO_ROOT)
        self.stack = [None] * depth

        limit = 1 << depth
        if limit < length:
            raise Exception(f"cannot handle iterate length {length} bottom nodes "
                            f"in subtree of depth {depth} deep (limit {limit} nodes)")
Example #9
0
    def __init__(self, anchor: Node, depth: int, length: int, elem_type: Type[BasicView]):
        self.anchor = anchor
        self.depth = depth
        self.length = length
        self.i = 0
        self.rootIndex = 0
        self.currentRoot = RootNode(ZERO_ROOT)
        self.stack = [None] * depth
        self.elem_type = elem_type

        self.per_node = 32 // elem_type.type_byte_length()
        self.j = self.per_node

        limit = (1 << depth) * self.per_node

        if limit < length:
            raise Exception(f"cannot handle iterate length {length} bottom subviews ({self.per_node} per node) "
                            f"in subtree of depth {depth} deep (limit {limit} subviews)")
Example #10
0
def pack_byte_ints_to_chunks(items: Iterable[int]) -> PyList[Node]:
    return [
        RootNode(Root(b"".join(map(byte_int_to_byte, chunk_bytes))))
        for chunk_bytes in grouper(items, 32, fillvalue=0)
    ]
Example #11
0
 def get_backing(self) -> Node:
     bytez = self.encode_bytes()
     return RootNode(Root(bytez + b"\x00" * (32 - len(bytez))))
Example #12
0
 def backing_from_base(self, base: Node, i: int) -> Node:
     section_bytez = self.encode_bytes()
     chunk_bytez = base.root[:len(section_bytez) *
                             i] + section_bytez + base.root[
                                 len(section_bytez) * (i + 1):]
     return RootNode(Root(chunk_bytez))