1 """Binary encodings for bup."""
3 # Copyright (C) 2010 Rob Browning
5 # This code is covered under the terms of the GNU Library General
6 # Public License as described in the bup LICENSE file.
8 # Variable length integers are encoded as vints -- see lucene.
10 from __future__ import absolute_import
11 from io import BytesIO
14 from bup import compat
17 def write_vuint(port, x):
19 bytes_from_uint = compat.bytes_from_uint
21 raise Exception("vuints must not be negative")
23 write(bytes_from_uint(0))
29 write(bytes_from_uint(0x80 | seven_bits))
31 write(bytes_from_uint(seven_bits))
38 raise EOFError('encountered EOF while reading vuint')
39 assert isinstance(c, bytes)
47 result |= ((b & 0x7f) << offset)
51 raise EOFError('encountered EOF while reading vuint')
53 result |= (b << offset)
58 def write_vint(port, x):
59 # Sign is handled with the second bit of the first byte. All else
62 bytes_from_uint = compat.bytes_from_uint
64 write(bytes_from_uint(0))
68 sign_and_six_bits = (x & 0x3f) | 0x40
70 sign_and_six_bits = x & 0x3f
73 write(bytes_from_uint(0x80 | sign_and_six_bits))
76 write(bytes_from_uint(sign_and_six_bits))
82 raise EOFError('encountered EOF while reading vint')
83 assert isinstance(c, bytes)
87 # Handle first byte with sign bit specially.
103 result |= ((b & 0x7f) << offset)
107 raise EOFError('encountered EOF while reading vint')
109 result |= (b << offset)
117 def write_bvec(port, x):
118 write_vuint(port, len(x))
128 port.read(read_vuint(port))
130 def send(port, types, *args):
131 if len(types) != len(args):
132 raise Exception('number of arguments does not match format string')
133 for (type, value) in zip(types, args):
135 write_vuint(port, value)
137 write_vint(port, value)
139 write_bvec(port, value)
141 raise Exception('unknown xpack format string item "' + type + '"')
143 def recv(port, types):
147 result.append(read_vuint(port))
149 result.append(read_vint(port))
151 result.append(read_bvec(port))
153 raise Exception('unknown xunpack format string item "' + type + '"')
156 def pack(types, *args):
158 send(port, types, *args)
159 return port.getvalue()
161 def unpack(types, data):
163 return recv(port, types)