blob: c40bb5f6177c03ad26cc5a12e889563cb2ae06f7 [file] [log] [blame]
# Copyright 2016 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.
import os
import struct
import sys
def write_uvarint(w, val):
"""Writes a varint value to the supplied file-like object.
Args:
w (object): A file-like object to write to. Must implement write.
val (number): The value to write. Must be >= 0.
Returns (int): The number of bytes that were written.
Raises:
ValueError if 'val' is < 0.
"""
if val < 0:
raise ValueError('Cannot encode negative value, %d' % (val,))
count = 0
while val > 0 or count == 0:
byte = (val & 0b01111111)
val >>= 7
if val > 0:
byte |= 0b10000000
w.write(struct.pack('B', byte))
count += 1
return count
def read_uvarint(r):
"""Reads a uvarint from a stream.
This is targeted towards testing, and will not be used in production code.
Args:
r (object): A file-like object to read from. Must implement read.
Returns: (value, count)
value (int): The decoded varint number.
count (int): The number of bytes that were read from 'r'.
Raises:
ValueError if the encoded varint is not terminated.
"""
count = 0
result = 0
while True:
byte = r.read(1)
if len(byte) == 0:
raise ValueError('UVarint was not terminated')
byte = struct.unpack('B', byte)[0]
result |= ((byte & 0b01111111) << (7 * count))
count += 1
if byte & 0b10000000 == 0:
break
return result, count