[PATCH 02 of 14 V3] util: implement varint functions
Augie Fackler
raf at durin42.com
Fri Jan 19 20:59:36 EST 2018
On Sat, Jan 20, 2018 at 12:47:07AM +0100, Boris Feld wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc at gmail.com>
> # Date 1516398755 -3600
> # Fri Jan 19 22:52:35 2018 +0100
> # Node ID 5dbc3c53c923b8d11b5efcaf0f415b3d8c8c5180
> # Parent 15f7795f96a5f9acb3ed2e640fcec82f3ccd6f53
> # EXP-Topic b2-stream
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 5dbc3c53c923
> util: implement varint functions
>
also candidates for netutil imo, or maybe protoutil (readexactly also
fits in the same bucket)
> This will be useful in an incoming version-2 of the stream format.
>
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -3874,3 +3874,73 @@ def readexactly(stream, n):
> " (got %d bytes, expected %d)")
> % (len(s), n))
> return s
> +
> +def uvarintencode(value):
> + """Encode an unsigned integer value to a varint.
> +
> + A varint is a variable length integer of 1 or more bytes. Each byte
> + except the last has the most significant bit set. The lower 7 bits of
> + each byte store the 2's complement representation, least significant group
> + first.
> +
> + >>> uvarintencode(0)
> + '\\x00'
> + >>> uvarintencode(1)
> + '\\x01'
> + >>> uvarintencode(127)
> + '\\x7f'
> + >>> uvarintencode(1337)
> + '\\xb9\\n'
> + >>> uvarintencode(65536)
> + '\\x80\\x80\\x04'
> + >>> uvarintencode(-1)
> + Traceback (most recent call last):
> + ...
> + ProgrammingError: negative value for uvarint: -1
> + """
> + if value < 0:
> + raise error.ProgrammingError('negative value for uvarint: %d'
> + % value)
> + bits = value & 0x7f
> + value >>= 7
> + bytes = []
> + while value:
> + bytes.append(pycompat.bytechr(0x80 | bits))
> + bits = value & 0x7f
> + value >>= 7
> + bytes.append(pycompat.bytechr(bits))
> +
> + return ''.join(bytes)
> +
> +def uvarintdecodestream(fh):
> + """Decode an unsigned variable length integer from a stream.
> +
> + The passed argument is anything that has a ``.read(N)`` method.
> +
> + >>> try:
> + ... from StringIO import StringIO as BytesIO
> + ... except ImportError:
> + ... from io import BytesIO
> + >>> uvarintdecodestream(BytesIO(b'\\x00'))
> + 0
> + >>> uvarintdecodestream(BytesIO(b'\\x01'))
> + 1
> + >>> uvarintdecodestream(BytesIO(b'\\x7f'))
> + 127
> + >>> uvarintdecodestream(BytesIO(b'\\xb9\\n'))
> + 1337
> + >>> uvarintdecodestream(BytesIO(b'\\x80\\x80\\x04'))
> + 65536
> + >>> uvarintdecodestream(BytesIO(b'\\x80'))
> + Traceback (most recent call last):
> + ...
> + Abort: stream ended unexpectedly (got 0 bytes, expected 1)
> + """
> + result = 0
> + shift = 0
> + while True:
> + byte = ord(readexactly(fh, 1))
> + result |= ((byte & 0x7f) << shift)
> + if not (byte & 0x80):
> + return result
> + shift += 7
More information about the Mercurial-devel
mailing list