def read(self, reader: BitStreamReader, size: int = 0) -> None: """ Reads array from the bit stream. :param reader: Bit stream from which to read. :param size: Number of elements to read or None in case of implicit or auto arrays. :raises PythonRuntimeException: If the array does not have elements with constant bit size. """ self._raw_array.clear() if self._is_implicit: if not self._array_traits.HAS_BITSIZEOF_CONSTANT: raise PythonRuntimeException( "Array: Implicit array elements must have constant bit size!" ) element_size = self._array_traits.bitsizeof() remaining_bits = reader.buffer_bitsize - reader.bitposition read_size = remaining_bits // element_size for index in range(read_size): self._raw_array.append(self._array_traits.read(reader, index)) else: if self._is_auto: read_size = reader.read_varsize() else: read_size = size for index in range(read_size): if self._check_offset_method is not None: reader.alignto(8) self._check_offset_method(index, reader.bitposition) self._raw_array.append(self._array_traits.read(reader, index))
def test_alignto(self): reader = BitStreamReader(bytes(1)) reader.alignto(1) self.assertEqual(0, reader.bitposition) reader.read_bits(1) self.assertEqual(1, reader.bitposition) reader.alignto(1) self.assertEqual(1, reader.bitposition) reader.alignto(4) self.assertEqual(4, reader.bitposition)
def _testImpl(self, writeMethod, readMethod, values, maxStartBitPos): for bitPos in range(maxStartBitPos): writer = BitStreamWriter() if bitPos > 0: writer.writeBits(0, bitPos) for value in values: writeMethod(writer, value) reader = BitStreamReader(buffer=writer.getByteArray()) if bitPos > 0: reader.readBits(bitPos) for value in values: self.assertEqual(value, readMethod(reader), "[bitPos=%d]" % bitPos)
def _test_impl(self, write_method, read_method, values, max_start_bit_pos): for bit_pos in range(max_start_bit_pos): writer = BitStreamWriter() if bit_pos > 0: writer.write_bits(0, bit_pos) for value in values: write_method(writer, value) reader = BitStreamReader(buffer=writer.byte_array) if bit_pos > 0: reader.read_bits(bit_pos) for value in values: self.assertEqual(value, read_method(reader), "[bit_pos=%d]" % bit_pos)
def _testBitsImpl(self, writeMethod, readMethod, values, numBits): for bitPos in range(numBits): writer = BitStreamWriter() if bitPos > 0: writer.writeBits(0, bitPos) for value in values: writeMethod(writer, value, numBits) reader = BitStreamReader(buffer=writer.getByteArray()) if bitPos > 0: reader.readBits(bitPos) for value in values: self.assertEqual(value, readMethod(reader, numBits), "[numBits=%d, bitPos=%d]" % (numBits, bitPos))
def _test_bits_impl(self, write_method, read_method, values, numbits): for bit_pos in range(numbits): writer = BitStreamWriter() if bit_pos > 0: writer.write_bits(0, bit_pos) for value in values: write_method(writer, value, numbits) reader = BitStreamReader(buffer=writer.byte_array) if bit_pos > 0: reader.read_bits(bit_pos) for value in values: self.assertEqual(value, read_method(reader, numbits), f"[numbits={numbits}, bit_pos={bit_pos}]")
def testReadVarInt(self): reader = BitStreamReader(b'\x00\x80') self.assertEqual(0, reader.readVarInt()) self.assertEqual(8, reader.getBitPosition()) self.assertEqual(INT64_MIN, reader.readVarInt()) self.assertEqual(16, reader.getBitPosition()) with self.assertRaises(PythonRuntimeException): reader.readVarInt()
def test_read_unaligned_data(self): # number expected to read at offset test_value = 123 for offset in range(65): buffer = bytearray((8 + offset + 7) // 8) # write test value at offset to data buffer buffer[offset // 8] = test_value >> (offset % 8) if offset % 8 != 0: # don't write behind the buffer buffer[offset // 8 + 1] = 0xff & test_value << (8 - offset % 8) bitbuffer = BitBuffer(buffer, 8 + offset) reader = BitStreamReader.from_bitbuffer(bitbuffer) # read offset bits self.assertEqual(0, reader.read_bits(offset)) # read magic number self.assertEqual(test_value, reader.read_bits(8), msg=("Offset: " + str(offset))) # check eof with self.assertRaises(PythonRuntimeException): reader.read_bits(1)
def _testFromReader(self, arrayTraits, arrayValues): array = Array(arrayTraits, arrayValues) writer = BitStreamWriter() array.write(writer) reader = BitStreamReader(writer.getByteArray()) readArray = Array.fromReader(arrayTraits, reader, len(arrayValues)) self.assertEqual(array, readArray)
def _test_from_reader(self, array_traits, array_values): array = Array(array_traits, array_values) writer = BitStreamWriter() array.write(writer) reader = BitStreamReader(writer.byte_array) read_array = Array.from_reader(array_traits, reader, len(array_values)) self.assertEqual(array, read_array)
def test_read_varsize(self): # overflow, 2^32 - 1 is too much (b'\x83\xFF\xFF\xFF\xFF') is the maximum) reader = BitStreamReader(b'\x87\xFF\xFF\xFF\xFF') with self.assertRaises(PythonRuntimeException): reader.read_varsize() # overflow, 2^36 - 1 is too much (b'\x83\xFF\xFF\xFF\xFF') is the maximum) reader = BitStreamReader(b'\xFF\xFF\xFF\xFF\xFF') with self.assertRaises(PythonRuntimeException): reader.read_varsize()
def read(reader: BitStreamReader, _index: int) -> BitBuffer: """ Reads Zserio extern bit buffer type from the bit stream. :param reader: Bit stream from which to read. :param _index: Not used. """ return reader.read_bitbuffer()
def read(reader: BitStreamReader, _index: int) -> bool: """ Reads Zserio bool type from the bit stream. :param reader: Bit stream from which to read. :param _index: Not used. """ return reader.read_bool()
def read(reader: BitStreamReader, _index: int) -> str: """ Reads Zserio string type from the bit stream. :param reader: Bit stream from which to read. :param _index: Not used. """ return reader.read_string()
def read(self, reader: BitStreamReader, _index: int) -> int: """ Reads signed fixed integer Zserio type from the bit stream. :param reader: Bit stream from which to read. :param _index: Not used. """ return reader.read_signed_bits(self._numbits)
def test_from_bitbuffer(self): bitbuffer = BitBuffer(bytes([0xAE, 0xEA, 0x80]), 17) reader = BitStreamReader.from_bitbuffer(bitbuffer) self.assertEqual(bitbuffer.bitsize, reader.buffer_bitsize) self.assertEqual(0xAEE, reader.read_bits(12)) self.assertEqual(0x0A, reader.read_bits(4)) self.assertEqual(0x01, reader.read_bits(1)) with self.assertRaises(PythonRuntimeException): reader.read_bits(1)
def testFromBitBuffer(self): bitBuffer = BitBuffer(bytes([0xAE, 0xEA, 0x80]), 17) reader = BitStreamReader.fromBitBuffer(bitBuffer) self.assertEqual(bitBuffer.getBitSize(), reader.getBufferBitSize()) self.assertEqual(0xAEE, reader.readBits(12)) self.assertEqual(0x0A, reader.readBits(4)) self.assertEqual(0x01, reader.readBits(1)) with self.assertRaises(PythonRuntimeException): reader.readBits(1)
def read(reader: BitStreamReader, _index: int) -> float: """ Reads Zserio float64 type from the bit stream. :param reader: Bit stream from which to read. :param _index: Not used. """ return reader.read_float64()
def read(reader: BitStreamReader, _index: int) -> int: """ Reads Zserio varint type from the bit stream. :param reader: Bit stream from which to read. :param _index: Not used. """ return reader.read_varint()
def _testRead(self, arrayTraits, arrayValues): def _checkOffsetMethod(_index, _bitOffset): pass array = Array(arrayTraits, arrayValues) writer = BitStreamWriter() array.write(writer) reader = BitStreamReader(writer.getByteArray()) emptyArray = Array(arrayTraits) emptyArray.read(reader, len(array.getRawArray())) self.assertEqual(array, emptyArray) autoArray = Array(arrayTraits, arrayValues, isAuto=True) writer = BitStreamWriter() autoArray.write(writer) reader = BitStreamReader(writer.getByteArray()) emptyAutoArray = Array(arrayTraits, isAuto=True) emptyAutoArray.read(reader, len(autoArray.getRawArray())) self.assertEqual(autoArray, emptyAutoArray) alignedArray = Array(arrayTraits, arrayValues, checkOffsetMethod=_checkOffsetMethod) writer = BitStreamWriter() alignedArray.write(writer) reader = BitStreamReader(writer.getByteArray()) emptyAlignedArray = Array(arrayTraits, checkOffsetMethod=_checkOffsetMethod) emptyAlignedArray.read(reader, len(alignedArray.getRawArray())) self.assertEqual(alignedArray, emptyAlignedArray) implicitArray = Array(arrayTraits, arrayValues, isImplicit=True) writer = BitStreamWriter() implicitArray.write(writer) reader = BitStreamReader(writer.getByteArray()) emptyImplicitArray = Array(arrayTraits, isImplicit=True) emptyImplicitArray.read(reader) # read implicit array can be bigger (for example, BoolArray) implicitRawArray = implicitArray.getRawArray() emptyImplicitRawArray = emptyImplicitArray.getRawArray() for index, implicitRawArrayElement in enumerate(implicitRawArray): self.assertEqual(implicitRawArrayElement, emptyImplicitRawArray[index])
def _test_read(self, array_traits, array_values): array = Array(array_traits, array_values) writer = BitStreamWriter() array.write(writer) reader = BitStreamReader(writer.byte_array) read_array = Array(array_traits) read_array.read(reader, len(array.raw_array)) self.assertEqual(array, read_array) auto_array = Array(array_traits, array_values, is_auto=True) writer = BitStreamWriter() auto_array.write(writer) reader = BitStreamReader(writer.byte_array) read_auto_array = Array(array_traits, is_auto=True) read_auto_array.read(reader, len(auto_array.raw_array)) self.assertEqual(auto_array, read_auto_array) aligned_array = Array( array_traits, array_values, check_offset_method=ArrayTest._check_offset_method) writer = BitStreamWriter() aligned_array.write(writer) reader = BitStreamReader(writer.byte_array) read_aligned_array = Array( array_traits, check_offset_method=ArrayTest._check_offset_method) read_aligned_array.read(reader, len(aligned_array.raw_array)) self.assertEqual(aligned_array, read_aligned_array) if array_traits.HAS_BITSIZEOF_CONSTANT and array_traits.bitsizeof( ) % 8 == 0: implicit_array = Array(array_traits, array_values, is_implicit=True) writer = BitStreamWriter() implicit_array.write(writer) reader = BitStreamReader(writer.byte_array) read_implicit_array = Array(array_traits, is_implicit=True) read_implicit_array.read(reader) self.assertEqual(implicit_array, read_implicit_array) elif not array_traits.HAS_BITSIZEOF_CONSTANT: with self.assertRaises(PythonRuntimeException): Array(array_traits, is_implicit=True).read(reader)
def _testRead(self, arrayTraits, arrayValues): def _checkOffsetMethod(_index, _bitOffset): pass array = Array(arrayTraits, arrayValues) writer = BitStreamWriter() array.write(writer) reader = BitStreamReader(writer.getByteArray()) readArray = Array(arrayTraits) readArray.read(reader, len(array.getRawArray())) self.assertEqual(array, readArray) autoArray = Array(arrayTraits, arrayValues, isAuto=True) writer = BitStreamWriter() autoArray.write(writer) reader = BitStreamReader(writer.getByteArray()) readAutoArray = Array(arrayTraits, isAuto=True) readAutoArray.read(reader, len(autoArray.getRawArray())) self.assertEqual(autoArray, readAutoArray) alignedArray = Array(arrayTraits, arrayValues, checkOffsetMethod=_checkOffsetMethod) writer = BitStreamWriter() alignedArray.write(writer) reader = BitStreamReader(writer.getByteArray()) readAlignedArray = Array(arrayTraits, checkOffsetMethod=_checkOffsetMethod) readAlignedArray.read(reader, len(alignedArray.getRawArray())) self.assertEqual(alignedArray, readAlignedArray) if arrayTraits.HAS_BITSIZEOF_CONSTANT and arrayTraits.bitSizeOf( ) % 8 == 0: implicitArray = Array(arrayTraits, arrayValues, isImplicit=True) writer = BitStreamWriter() implicitArray.write(writer) reader = BitStreamReader(writer.getByteArray()) readImplicitArray = Array(arrayTraits, isImplicit=True) readImplicitArray.read(reader) self.assertEqual(implicitArray, readImplicitArray) elif not arrayTraits.HAS_BITSIZEOF_CONSTANT: with self.assertRaises(PythonRuntimeException): Array(arrayTraits, isImplicit=True).read(reader)
def testReadBits(self): data = [0, 1, 255, 128, 127] reader = BitStreamReader(bytes(data)) for byte in data: self.assertEqual(byte, reader.readBits(8)) with self.assertRaises(PythonRuntimeException): reader.readBits(-1) self.assertEqual(0, reader.readBits(0)) # read 0 bits with self.assertRaises(PythonRuntimeException): reader.readBits(1) # no more bits available
def testFile(self): testFilename = "BitStreamTest.bin" writer = BitStreamWriter() writer.writeBits(13, 7) writer.writeString(testFilename) writer.writeVarInt(-123456) writer.toFile(testFilename) reader = BitStreamReader.fromFile(testFilename) self.assertEqual(13, reader.readBits(7)) self.assertEqual(testFilename, reader.readString()) self.assertEqual(-123456, reader.readVarInt())
def test_file(self): test_filename = "BitStreamTest.bin" writer = BitStreamWriter() writer.write_bits(13, 7) writer.write_string(test_filename) writer.write_varint(-123456) writer.to_file(test_filename) reader = BitStreamReader.from_file(test_filename) self.assertEqual(13, reader.read_bits(7)) self.assertEqual(test_filename, reader.read_string()) self.assertEqual(-123456, reader.read_varint())
def _test_array_normal(self, array_traits, array_values, expected_bitsize): for i in range(8): array = Array(array_traits, array_values) bitsize = array.bitsizeof(i) self.assertEqual(expected_bitsize, bitsize) self.assertEqual(i + bitsize, array.initialize_offsets(i), i) writer = BitStreamWriter() if i > 0: writer.write_bits(0, i) array.write(writer) self.assertEqual(i + bitsize, writer.bitposition, i) from_reader = BitStreamReader(writer.byte_array, writer.bitposition) self.assertEqual(0, from_reader.read_bits(i)) read_array_from_reader = Array.from_reader(array_traits, from_reader, len(array_values)) self.assertEqual(array, read_array_from_reader, i) reader = BitStreamReader(writer.byte_array, writer.bitposition) if i > 0: self.assertEqual(0, reader.read_bits(i)) read_array = Array(array_traits) read_array.read(reader, len(array_values)) self.assertEqual(array, read_array, i)
def _test_packed_array_auto(self, array_traits, array_values, expected_bitsize): for i in range(8): array = Array(array_traits, array_values, is_auto=True) bitsize = array.bitsizeof_packed(i) if expected_bitsize is not None: self.assertEqual(expected_bitsize, bitsize) self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i) writer = BitStreamWriter() if i > 0: writer.write_bits(0, i) array.write_packed(writer) self.assertEqual(i + bitsize, writer.bitposition, i) from_reader = BitStreamReader(writer.byte_array, writer.bitposition) self.assertEqual(0, from_reader.read_bits(i)) read_array_from_reader = Array.from_reader_packed(array_traits, from_reader, is_auto=True) self.assertEqual(array, read_array_from_reader, i) reader = BitStreamReader(writer.byte_array, writer.bitposition) if i > 0: self.assertEqual(0, reader.read_bits(i)) read_array = Array(array_traits, is_auto=True) read_array.read_packed(reader) self.assertEqual(array, read_array, i)
def read(self, reader: BitStreamReader, size: int = 0) -> None: """ Reads array from the bit stream. :param reader: Bit stream from which to read. :param size: Number of elements to read or None in case of implicit or auto arrays. :raises PythonRuntimeException: If the array does not have elements with constant bit size. """ self._rawArray.clear() if self._isImplicit: if not self._arrayTraits.HAS_BITSIZEOF_CONSTANT: raise PythonRuntimeException("Array: Implicit array elements must have constant bit size!") elementSize = self._arrayTraits.bitSizeOf() remainingBits = reader.getBufferBitSize() - reader.getBitPosition() readSize = remainingBits // elementSize for index in range(readSize): self._rawArray.append(self._arrayTraits.read(reader, index)) else: if self._isAuto: readSize = reader.readVarSize() else: readSize = size for index in range(readSize): if self._checkOffsetMethod is not None: reader.alignTo(8) self._checkOffsetMethod(index, reader.getBitPosition()) self._rawArray.append(self._arrayTraits.read(reader, index))
def test_constructor(self): reader = BitStreamReader(bytes([0xAE, 0xEA, 0x80]), 17) self.assertEqual(0xAE, reader.read_bits(8)) self.assertEqual(0xEA, reader.read_bits(8)) self.assertEqual(0x01, reader.read_bits(1)) with self.assertRaises(PythonRuntimeException): reader.read_bits(1) # no more bits available
def test_bitposition(self): writer = BitStreamWriter() writer.write_bits(0xaaaa, 16) self.assertEqual(16, writer.bitposition) writer.write_bits(0xff, 8) self.assertEqual(24, writer.bitposition) reader = BitStreamReader(buffer=writer.byte_array) self.assertEqual(0xaaaa, reader.read_bits(16)) self.assertEqual(16, reader.bitposition) reader.bitposition = 8 self.assertEqual(8, reader.bitposition) self.assertEqual(0xaaff, reader.read_bits(16)) reader.bitposition = 13 self.assertEqual(13, reader.bitposition) self.assertEqual(0x02, reader.read_bits(3)) self.assertEqual(16, reader.bitposition) self.assertEqual(0xff, reader.read_bits(8)) self.assertEqual(24, reader.bitposition) reader.bitposition = 0 self.assertEqual(0, reader.bitposition) self.assertEqual(0xaaaaff, reader.read_bits(24))