+def encode_element_size(size, min_length=None, max_length=EBMLMaxSizeLength):
+ """
+
+ Encode the size of an EBML element as a vint, optionally with a minimum length.
+
+ :arg size: the element size, or None if undefined
+ :type size: int or None
+ :arg min_length: the minimum length, in bytes, of the resultant vint
+ :type min_length: int
+ :arg max_length: the maximum length, in bytes, of the vint storing the element size (defaults to :data:`EBMLMaxSizeLength`)
+ :type max_length: int
+ :returns: bytearray
+
+ """
+
+
+ if size is not None:
+ size_bits = bin(size).lstrip('-0b')
+ size_bit_length = len(size_bits)
+ length_required = (abs(size_bit_length - 1) // 7) + 1
+ if size_bit_length % 7 == 0 and '1' in size_bits and '0' not in size_bits:
+ length_required += 1
+ length = max(length_required, min_length)
+
+ alignment_bit_length = 0
+ while ((length + alignment_bit_length + size_bit_length) // 8) < length:
+ alignment_bit_length += 1
+ else:
+ length = min_length or 1
+ required_bits = (length * 8) - length
+ size_bit_length = required_bits
+ size = (2**required_bits) - 1
+ alignment_bit_length = 0
+
+ if length > max_length:
+ raise ValueError('Unable to encode size (%i) with length %i (longer than limit of %i)' % (size, length, max_length))
+
+ data = bytearray(length)
+ bytes_written = 0
+ marker_written = False
+ while bytes_written < length:
+ index = (length - bytes_written) - 1
+ if size:
+ data[index] = size & 0b11111111
+ size = size >> 8
+ if not size and not size_bit_length % 8 == 0:
+ if alignment_bit_length < (8 - (size_bit_length % 8)):
+ mask = 0b10000000 >> ((length - 1) % 8)
+ data[index] = data[index] | mask
+ alignment_bit_length = 0
+ marker_written = True
+ else:
+ alignment_bit_length -= (8 - (size_bit_length % 8))
+ bytes_written += 1
+ else:
+ if alignment_bit_length:
+ if alignment_bit_length < 8:
+ data[index] = 0b10000000 >> ((length - 1) % 8)
+ alignment_bit_length = 0
+ bytes_written += 1
+ marker_written = True
+ else:
+ data[index] = 0b00000000
+ alignment_bit_length -= 8
+ bytes_written += 1
+ else:
+ remaining_bytes = length - bytes_written
+ if not marker_written:
+ data[(remaining_bytes - 1)] = 0b00000001
+ zero_range = range(0, (remaining_bytes - 1))
+ else:
+ zero_range = range(0, remaining_bytes)
+ for index in zero_range:
+ data[index] = 0b00000000
+ bytes_written += remaining_bytes
+
+ return data
+
+
+def write_element_size(size, stream, min_length=None, max_length=EBMLMaxSizeLength):
+ """
+
+ Write the size of an EBML element to stream, optionally with a minimum length.
+
+ :arg size: the element size, or None if undefined
+ :type size: int or None
+ :arg min_length: the minimum length, in bytes, to write
+ :type min_length: int
+ :arg max_length: the maximum length, in bytes, to write (defaults to :data:`EBMLMaxSizeLength`)
+ :type max_length: int
+ :returns: None
+
+ """
+
+ stream.write(encode_element_size(size, min_length, max_length))
+
+
+def read_element_id(stream, max_length=EBMLMaxIDLength):