2 from .exceptions import *
9 def _read_vint_to_bytearray(stream, max_width=EBMLMaxSizeLength):
12 Reads a vint from stream and returns a bytearray containing all of the bytes without doing any decoding.
14 :arg stream: the source of the bytes
15 :type stream: a file-like object
16 :arg max_width: the maximum length, in bytes, of the vint (defaults to :data:`EBMLMaxSizeLength`)
23 vint_bytes = bytearray()
25 while not marker_found:
27 if vint_len > max_width:
28 raise ParseError('vint exceeds max_width (%(max_width)i)' % {
29 'max_width': max_width
31 byte = ord(stream.read(1))
32 vint_bytes.append(byte)
33 for pos in range(0, 8):
34 mask = 0b10000000 >> pos
40 remaining_bytes_len = vint_len - len(vint_bytes)
41 if remaining_bytes_len > 0:
42 vint_bytes.extend(ord(remaining_byte) for remaining_byte in stream.read(remaining_bytes_len))
44 if len(vint_bytes) != vint_len:
45 raise ParseError('Unable to read truncated vint of width %(vint_len)s from stream (%(vint_bytes)s bytes available)' % {
47 'vint_bytes': len(vint_bytes)
53 def read_element_size(stream, max_width=EBMLMaxSizeLength):
56 Reads an EBML element size vint from stream and returns a tuple containing:
58 * the size as an integer, or None if the size is undefined
59 * the length in bytes of the size descriptor (the vint) itself
61 :arg stream: the source of the bytes
62 :type stream: a file-like object
63 :arg max_width: the maximum length, in bytes, of the vint storing the element size (defaults to :data:`EBMLMaxSizeLength`)
69 vint_bytes = _read_vint_to_bytearray(stream, max_width)
70 vint_len = len(vint_bytes)
72 int_bytes = vint_bytes[((vint_len - 1) // 8):]
73 first_byte_mask = 0b10000000 >> ((vint_len - 1) % 8)
76 value = int_bytes[0] & (first_byte_mask - 1)
78 if value == (first_byte_mask - 1):
81 for int_byte in int_bytes[1:]:
82 if int_byte == 0b11111111:
84 value = (value << 8) | int_byte
86 if max_bytes == len(int_bytes):
89 return value, vint_len
92 def read_element_id(stream, max_width=EBMLMaxIDLength):
95 Reads an EBML element ID vint from stream and returns a tuple containing:
97 * the ID as an integer
98 * the length in bytes of the ID descriptor (the vint) itself
100 :arg stream: the source of the bytes
101 :type stream: a file-like object
102 :arg max_width: the maximum length, in bytes, of the vint storing the element ID (defaults to :data:`EBMLMaxIDLength`)
108 vint_bytes = _read_vint_to_bytearray(stream, max_width)
109 vint_len = len(vint_bytes)
115 for vint_byte in vint_bytes:
116 if vint_byte == 0b11111111:
120 value = (value << 8) | vint_byte
122 if max_bytes == vint_len:
123 raise ReservedElementIDError('All value bits set to 1')
124 elif min_bytes == vint_len:
125 raise ReservedElementIDError('All value bits set to 0')
127 return value, vint_len