示例#1
0
 def transcribe_value(B):
     ''' Transcribe this `Block`, the inverse of parse_value.
 '''
     transcription = []
     is_indirect = B.indirect
     span = B.span
     if is_indirect:
         # aside from the span, everything else comes from the superblock
         B = B.superblock
     block_type = B.type
     assert block_type >= 0, "block_type(%s) => %d" % (B, B.type)
     block_typed = block_type != BlockType.BT_HASHCODE
     flags = ((F_BLOCK_INDIRECT if is_indirect else 0)
              | (F_BLOCK_TYPED if block_typed else 0)
              | 0  # no F_BLOCK_TYPE_FLAGS
              )
     transcription.append(BSUInt.transcribe_value(flags))
     transcription.append(BSUInt.transcribe_value(span))
     if block_typed:
         transcription.append(BSUInt.transcribe_value(block_type))
     # no block_type_flags
     if block_type == BlockType.BT_HASHCODE:
         transcription.append(B.hashcode.transcribe_b())
     elif block_type == BlockType.BT_RLE:
         transcription.append(B.octet)
     elif block_type == BlockType.BT_LITERAL:
         transcription.append(B.data)
     elif block_type == BlockType.BT_SUBBLOCK:
         transcription.append(BSUInt.transcribe_value(B.offset))
         transcription.append(BlockRecord.transcribe_value(B.superblock))
     else:
         raise ValueError("unsupported Block type 0x%02x: %s" %
                          (block_type, B))
     block_bs = b''.join(flatten_transcription(transcription))
     return BSData(block_bs).transcribe()
示例#2
0
 def do(stream):
     ''' Return the number of indexed blocks in `local_store`.
 '''
     local_store = stream._local_store
     if local_store is None:
         raise ValueError("no local_store, request rejected")
     return bytes(BSUInt(len(local_store)))
示例#3
0
 def parse_value(bfr):
     ''' Unserialise a serialised Dirent.
 '''
     type_ = BSUInt.parse_value(bfr)
     flags = DirentFlags(BSUInt.parse_value(bfr))
     if flags & DirentFlags.HASNAME:
         flags ^= DirentFlags.HASNAME
         name = BSString.parse_value(bfr)
     else:
         name = ""
     if flags & DirentFlags.HASMETA:
         flags ^= DirentFlags.HASMETA
         metatext = BSString.parse_value(bfr)
     else:
         metatext = None
     uu = None
     if flags & DirentFlags.HASUUID:
         flags ^= DirentFlags.HASUUID
         uu = UUID(bytes=bfr.take(16))
     if flags & DirentFlags.NOBLOCK:
         flags ^= DirentFlags.NOBLOCK
         block = None
     else:
         block = BlockRecord.parse_value(bfr)
     if flags & DirentFlags.HASPREVDIRENT:
         flags ^= DirentFlags.HASPREVDIRENT
         prev_dirent_blockref = BlockRecord.parse_value(bfr)
     else:
         prev_dirent_blockref = None
     if flags & DirentFlags.EXTENDED:
         flags ^= DirentFlags.EXTENDED
         extended_data = BSData.parse_value(bfr)
     else:
         extended_data = None
     if flags:
         warning("%s.parse_value: unexpected extra flags: 0x%02x",
                 cls.__name__, flags)
     E = _Dirent.from_components(type_,
                                 name,
                                 meta=metatext,
                                 uuid=uu,
                                 block=block)
     E._prev_dirent_blockref = prev_dirent_blockref
     E.ingest_extended_data(extended_data)
     return E
示例#4
0
 def transcribe(self):
     ''' Transcribe this packet.
 '''
     is_request = self.is_request
     channel = self.channel
     bss = [
         BSUInt.transcribe_value(self.tag),
         BSUInt.transcribe_value((0x01 if channel != 0 else 0x00)
                                 | (0x02 if is_request else 0x00)
                                 | (self.flags << 2)),
         BSUInt.transcribe_value(channel) if channel != 0 else b'',
         BSUInt.transcribe_value(self.rq_type) if is_request else b'',
         self.payload
     ]
     length = sum(len(bs) for bs in bss)
     # spit out a BSData manually to avoid pointless bytes.join
     yield BSUInt.transcribe_value(length)
     yield bss
示例#5
0
   class hashclass(HashCode):
       ''' `HashCode` subclass.
 '''
       __slots__ = ()
       HASHNAME = hashname
       HASHFUNC = hashfunc
       HASHLEN = hashlen
       HASHENUM = hashenum
       HASHENUM_BS = bytes(BSUInt(hashenum))
       HASHLEN_ENCODED = len(HASHENUM_BS) + HASHLEN
示例#6
0
 def parse(cls, bfr):
     ''' Parse a `CompressibleDataRecord` from a buffer.
 '''
     flags = BSUInt.parse_value(bfr)
     data = BSData.parse_value(bfr)
     is_compressed = (flags & cls.FLAG_COMPRESSED) != 0
     if is_compressed:
         flags &= ~cls.FLAG_COMPRESSED
     if flags:
         raise ValueError("unsupported flags: 0x%02x" % (flags, ))
     return cls(_data=data, is_compressed=is_compressed)
示例#7
0
 def __len__(self):
     try:
         flags, payload = self.do(LengthRequest())
     except StoreError as e:
         error("connection: %s", e)
         return None
     assert flags == 0
     length, offset = BSUInt.parse_value_from_bytes(payload)
     if offset < len(payload):
         warning("unparsed bytes after BSUInt(length): %r",
                 payload[offset:])
     return length
示例#8
0
 def parse(cls, bfr):
     ''' Parse a packet from a buffer.
 '''
     raw_payload = BSData.parse_value(bfr)
     payload_bfr = CornuCopyBuffer([raw_payload])
     self = cls()
     # pylint: disable=attribute-defined-outside-init
     self.tag = BSUInt.parse_value(payload_bfr)
     flags = BSUInt.parse_value(payload_bfr)
     has_channel = (flags & 0x01) != 0
     self.is_request = (flags & 0x02) != 0
     flags >>= 2
     self.flags = flags
     if has_channel:
         self.channel = BSUInt.parse_value(payload_bfr)
     else:
         self.channel = 0
     if self.is_request:
         self.rq_type = BSUInt.parse_value(payload_bfr)
     self.payload = b''.join(payload_bfr)
     return self
示例#9
0
 def transcribe(self):
     ''' Serialise to binary format.
 '''
     E = self.dirent
     flags = 0
     type_ = E.type
     if E.name:
         flags |= DirentFlags.HASNAME
     meta = None if E.isindirect else E.meta
     if meta:
         flags |= DirentFlags.HASMETA
     if E.uuid:
         flags |= DirentFlags.HASUUID
     block = None if type_ is DirentType.INDIRECT else E.block
     if block is None:
         flags |= DirentFlags.NOBLOCK
     if E._prev_dirent_blockref is not None:
         flags |= DirentFlags.HASPREVDIRENT
     extended_data = E.get_extended_data()
     if extended_data:
         flags |= DirentFlags.EXTENDED
     yield BSUInt.transcribe_value(type_)
     yield BSUInt.transcribe_value(flags)
     if flags & DirentFlags.HASNAME:
         yield BSString.transcribe_value(E.name)
     if flags & DirentFlags.HASMETA:
         yield BSString.transcribe_value(meta.textencode())
     if flags & DirentFlags.HASUUID:
         bs = E.uuid.bytes
         if len(bs) != 16:
             raise RuntimeError("len(E.uuid.bytes) != 16: %r" % (bs, ))
         yield bs
     if not flags & DirentFlags.NOBLOCK:
         yield BlockRecord.transcribe_value(block)
     if flags & DirentFlags.HASPREVDIRENT:
         assert isinstance(E._prev_dirent_blockref, _Block)
         yield BlockRecord.transcribe_value(E._prev_dirent_blockref)
     if flags & DirentFlags.EXTENDED:
         yield extended_data
示例#10
0
 def parse(cls, bfr, *, parse_flags):
     ''' Parse a HashCodesRequest from a buffer and construct.
 '''
     after = (parse_flags & 0x01) != 0
     has_start_hashcode = (parse_flags & 0x02) != 0
     extra_flags = parse_flags & ~0x03
     if extra_flags:
         raise ValueError("extra flags: 0x%02x" % (extra_flags, ))
     hashname = BSString.parse_value(bfr)
     hashclass = HashCode.by_index(hashname)
     if has_start_hashcode:
         start_hashcode = HashCodeField.parse_value(bfr)
         if type(start_hashcode) is not hashclass:  # pylint: disable=unidiomatic-typecheck
             raise ValueError(
                 "request hashclass %s does not match start_hashcode class %s"
                 % (hashclass, type(start_hashcode)))
     else:
         start_hashcode = None
     length = BSUInt.parse_value(bfr)
     return cls(after=after,
                hashclass=hashclass,
                start_hashcode=start_hashcode,
                length=length)
示例#11
0
    def parse_value(bfr):
        ''' Decode a Block reference from a buffer.

        Format is a `BSData` holding this encoded data:

            BS(flags)
              0x01 indirect blockref
              0x02 typed: type follows, otherwise BT_HASHCODE
              0x04 type flags: per type flags follow type
            BS(span)
            [BS(type)]
            [BS(type_flags)]
            union {
              type BT_HASHCODE: hash
              type BT_RLE: octet-value (repeat span times to get data)
              type BT_LITERAL: raw-data (span bytes)
              type BT_SUBBLOCK: suboffset, super block
            }

        Even though this is all decodable without the leading length
        we use a leading length so that future encodings do not
        prevent parsing any following data.
    '''
        raw_encoding = BSData.parse_value(bfr)
        blockref_bfr = CornuCopyBuffer.from_bytes(raw_encoding)
        flags = BSUInt.parse_value(blockref_bfr)
        is_indirect = bool(flags & F_BLOCK_INDIRECT)
        is_typed = bool(flags & F_BLOCK_TYPED)
        has_type_flags = bool(flags & F_BLOCK_TYPE_FLAGS)
        unknown_flags = flags & ~(F_BLOCK_INDIRECT | F_BLOCK_TYPED
                                  | F_BLOCK_TYPE_FLAGS)
        if unknown_flags:
            raise ValueError(
                "unexpected flags value (0x%02x) with unsupported flags=0x%02x"
                % (flags, unknown_flags))
        span = BSUInt.parse_value(blockref_bfr)
        if is_indirect:
            # With indirect blocks, the span is of the implied data, not
            # the referenced block's data. Therefore we build the referenced
            # block with a span of None and store the span in the indirect
            # block.
            ispan = span
            span = None
        # block type, default BT_HASHCODE
        if is_typed:
            block_type = BlockType(BSUInt.parse_value(blockref_bfr))
        else:
            block_type = BlockType.BT_HASHCODE
        if has_type_flags:
            type_flags = BSUInt.parse_value(blockref_bfr)
            if type_flags:
                warning("nonzero type_flags: 0x%02x", type_flags)
        else:
            type_flags = 0x00
        # instantiate type specific block ref
        if block_type == BlockType.BT_HASHCODE:
            hashcode = HashCode.from_buffer(blockref_bfr)
            B = HashCodeBlock(hashcode=hashcode, span=span)
        elif block_type == BlockType.BT_RLE:
            octet = blockref_bfr.take(1)
            B = RLEBlock(span, octet)
        elif block_type == BlockType.BT_LITERAL:
            data = blockref_bfr.take(span)
            B = LiteralBlock(data)
        elif block_type == BlockType.BT_SUBBLOCK:
            suboffset = BSUInt.parse_value(blockref_bfr)
            superB = BlockRecord.parse_value(blockref_bfr)
            # wrap inner Block in subspan
            B = SubBlock(superB, suboffset, span)
        else:
            raise ValueError("unsupported Block type 0x%02x" % (block_type, ))
        if is_indirect:
            B = IndirectBlock(B, span=ispan)
        if not blockref_bfr.at_eof():
            warning("unparsed data (%d bytes) follow Block %s",
                    len(raw_encoding) - blockref_bfr.offset, B)
        assert isinstance(B, _Block)
        return B
示例#12
0
 def transcribe(self):
     ''' Transcribe this data chunk as a data record.
 '''
     yield BSUInt.transcribe_value(self.flags)
     yield BSData.transcribe_value(self._data)
示例#13
0
 def transcribe(self):
     yield BSString.transcribe_value(self.hashclass.HASHNAME)
     start_hashcode = self.start_hashcode
     if start_hashcode is not None:
         yield HashCodeField.transcribe_value(start_hashcode)
     yield BSUInt.transcribe_value(self.length)
示例#14
0
 def transcribe_value(hashcode):
     ''' Serialise a hashcode.
 '''
     yield BSUInt.transcribe_value(hashcode.HASHENUM)
     yield hashcode
示例#15
0
 def parse_value(bfr):
     ''' Decode a serialised hash from the CornuCopyBuffer `bfr`.
 '''
     hashenum = BSUInt.parse_value(bfr)
     hashcls = HASHCLASS_BY_ENUM[hashenum]
     return hashcls.from_hashbytes(bfr.take(hashcls.HASHLEN))
示例#16
0
 def data_offset(self):
     ''' The offset of the data chunk within the transcribed `DataRecord`.
 '''
     return (len(BSUInt.transcribe_value(self.flags)) +
             BSData.data_offset_for(self._data))