1# Copyright 2016 The LUCI Authors. All rights reserved. 2# Use of this source code is governed under the Apache License, Version 2.0 3# that can be found in the LICENSE file. 4 5import os 6import struct 7import sys 8 9 10def write_uvarint(w, val): 11 """Writes a varint value to the supplied file-like object. 12 13 Args: 14 w (object): A file-like object to write to. Must implement write. 15 val (number): The value to write. Must be >= 0. 16 17 Returns (int): The number of bytes that were written. 18 19 Raises: 20 ValueError if 'val' is < 0. 21 """ 22 if val < 0: 23 raise ValueError('Cannot encode negative value, %d' % (val,)) 24 25 count = 0 26 while val > 0 or count == 0: 27 byte = (val & 0b01111111) 28 val >>= 7 29 if val > 0: 30 byte |= 0b10000000 31 32 w.write(struct.pack('B', byte)) 33 count += 1 34 return count 35 36 37def read_uvarint(r): 38 """Reads a uvarint from a stream. 39 40 This is targeted towards testing, and will not be used in production code. 41 42 Args: 43 r (object): A file-like object to read from. Must implement read. 44 45 Returns: (value, count) 46 value (int): The decoded varint number. 47 count (int): The number of bytes that were read from 'r'. 48 49 Raises: 50 ValueError if the encoded varint is not terminated. 51 """ 52 count = 0 53 result = 0 54 while True: 55 byte = r.read(1) 56 if len(byte) == 0: 57 raise ValueError('UVarint was not terminated') 58 59 byte = struct.unpack('B', byte)[0] 60 result |= ((byte & 0b01111111) << (7 * count)) 61 count += 1 62 if byte & 0b10000000 == 0: 63 break 64 return result, count 65