Пример #1
0
    def encode(self, compression: Optional[cmp.Compression] = None) -> bytes:
        """
        byte array representation of log entry.
        append CRC32 checksum of header and k/v
        -----------------------------------------------------------------------
        | block size | meta | key length | value length | key | value | crc32 |
        -----------------------------------------------------------------------
        """

        key, value, meta = self.key, self.value, self.meta

        if compression and compression.isenabled:
            key = compression.compress(key)
            value = compression.compress(value)

        header = self._encode_header(key=key, value=value, meta=meta)
        checksum = crc32(header)
        encoded = bytearray(header)
        checksum = crc32(key, checksum)
        encoded += key
        checksum = crc32(value, checksum)
        encoded += value
        encoded += uvarint.encode(checksum)
        block_size = uvarint.encode(len(encoded))

        return bytes([*block_size, *encoded])
Пример #2
0
async def test_write_message(fragmented_message: Tuple[StreamID, MplexFlag,
                                                       StreamData]):
    reader_mock, writer_mock = get_connection_mock("127.0.0.1", 7777)
    stream_id, flag, data = fragmented_message

    mplex_protocol = MplexProtocol(reader_mock, writer_mock)
    await mplex_protocol.write_message(
        MplexMessage(stream_id=stream_id, flag=flag, data=data))
    encoded_message = (uvarint.encode(stream_id << 3 | flag) +
                       uvarint.encode(len(data)) + data)

    writer_mock.write.assert_called_with(encoded_message)
    writer_mock.drain.assert_awaited()
Пример #3
0
async def test_read_message(fragmented_message: Tuple[StreamID, MplexFlag,
                                                      StreamData]):
    reader_mock, writer_mock = get_connection_mock("127.0.0.1", 7777)
    stream_id, flag, data = fragmented_message

    mplex_protocol = MplexProtocol(reader_mock, writer_mock)
    encoded_message = (uvarint.encode(stream_id << 3 | flag) +
                       uvarint.encode(len(data)) + data)
    reader_mock.feed_data(encoded_message)
    message = await mplex_protocol.read_message()
    assert isinstance(message, MplexMessage)
    assert message.stream_id == stream_id
    assert message.flag == flag
    assert message.data == data
Пример #4
0
async def test_read_uvarint_overflow():
    uvarint_overflow = bytearray(
        [0b10000000 for _ in range(UVARINT_MAX_BYTES + 1)])
    reader_mock, writer_mock = get_connection_mock("127.0.0.1", 7777)
    stream_id, flag = 12, MplexFlag.NEW_STREAM
    encoded_message = uvarint.encode(stream_id << 3 | flag) + uvarint_overflow
    reader_mock.feed_data(encoded_message)

    mplex_protocol = MplexProtocol(reader_mock, writer_mock)
    with pytest.raises(OverflowError):
        message = await mplex_protocol.read_message()
Пример #5
0
    def _encode_header(cls, key: types.Key, value: types.Value,
                       meta: int) -> bytes:
        """
        byte array representation of header fields/metadata
        ------------------------------------
        | meta | key length | value length |
        ------------------------------------
        """

        header_fields = [len(key), len(value)]
        header = bytearray([meta])

        for val in header_fields:
            header += uvarint.encode(val)

        return header
Пример #6
0
    def to_bytes(self):
        """

        """
        ba = []

        if bool(self._inferiors):
            # fixed width binary representation for all lower halves
            inferiors_bits = int(reduce(lambda a, b: a + b,
                                        map(lambda inf: ("{0:0%db}" % self._lower_bits).format(inf),
                                            self._inferiors)),
                                 2)
            inferiors_byte_count = max(1, math.ceil(inferiors_bits.bit_length() / 8.0))
        else:
            inferiors_byte_count = 0

        if bool(self._superiors):
            # negated unary representation for upper halves
            superiors_bits = int(reduce(lambda a, b: a + b,
                                        map(lambda sup: ("1" * sup) + "0",
                                            self._superiors)),
                                 2)

            superiors_byte_count = max(1, math.ceil(superiors_bits.bit_length() / 8.0))
        else:
            superiors_byte_count = 0

        header = uvarint.encode(0)  # EliasFano: 0, MultiLevelEliasFano: 1
        header += uvarint.encode(self._n)
        header += uvarint.encode(self._lower_bits)
        header += uvarint.encode(self._upper_bits)
        header += uvarint.encode(inferiors_byte_count)
        header += uvarint.encode(superiors_byte_count)
        ba.append(header)

        if inferiors_byte_count:
            ba.append(inferiors_bits.to_bytes(inferiors_byte_count, 'little', signed=False))

        if superiors_byte_count:
            ba.append(superiors_bits.to_bytes(superiors_byte_count, 'little', signed=False))

        return len(b''.join(ba)), b''.join(ba)
Пример #7
0
def get_encoded_message(stream_name: StreamName, flag: MplexFlag,
                        data: StreamData) -> bytes:
    encoded_message = (
        uvarint.encode(get_stream_id_from_name(stream_name) << 3 | flag) +
        uvarint.encode(len(data)) + data)
    return encoded_message
Пример #8
0
 def _encode_message(self, message: MplexMessage) -> bytes:
     return (
         uvarint.encode(message.stream_id << 3 | message.flag)
         + uvarint.encode(len(message.data))
         + message.data
     )
Пример #9
0
    def test_encode(self) -> None:
        decoded: int
        encoded: bytes

        for (decoded, encoded) in TestUvarint.all:
            self.assertEqual(uvarint.encode(decoded), encoded)