| # 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 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(chr(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 = ord(byte) |
| result |= ((byte & 0b01111111) << (7 * count)) |
| count += 1 |
| if byte & 0b10000000 == 0: |
| break |
| return result, count |