diff options
author | Dan Klein <danklei@cisco.com> | 2015-08-24 09:28:43 +0300 |
---|---|---|
committer | Dan Klein <danklei@cisco.com> | 2015-08-24 09:28:43 +0300 |
commit | 20eb7d362f9bce1951bd61ad3f78cf8f4267d1d5 (patch) | |
tree | b2c3fe1c721d5f6898b4bb8e81f7c68502e313e9 /src/console/zmq/utils/z85.py | |
parent | 49f6b00b58c3ec734218fcd69259771a42c157bd (diff) | |
parent | 651a7d779551e193bd9dbadbe8b2a02bdab231b4 (diff) |
Merge branch 'master' into dan_stateless
Diffstat (limited to 'src/console/zmq/utils/z85.py')
-rwxr-xr-x | src/console/zmq/utils/z85.py | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/console/zmq/utils/z85.py b/src/console/zmq/utils/z85.py new file mode 100755 index 00000000..1bb1784e --- /dev/null +++ b/src/console/zmq/utils/z85.py @@ -0,0 +1,56 @@ +"""Python implementation of Z85 85-bit encoding + +Z85 encoding is a plaintext encoding for a bytestring interpreted as 32bit integers. +Since the chunks are 32bit, a bytestring must be a multiple of 4 bytes. +See ZMQ RFC 32 for details. + + +""" + +# Copyright (C) PyZMQ Developers +# Distributed under the terms of the Modified BSD License. + +import sys +import struct + +PY3 = sys.version_info[0] >= 3 +# Z85CHARS is the base 85 symbol table +Z85CHARS = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#" +# Z85MAP maps integers in [0,84] to the appropriate character in Z85CHARS +Z85MAP = dict([(c, idx) for idx, c in enumerate(Z85CHARS)]) + +_85s = [ 85**i for i in range(5) ][::-1] + +def encode(rawbytes): + """encode raw bytes into Z85""" + # Accepts only byte arrays bounded to 4 bytes + if len(rawbytes) % 4: + raise ValueError("length must be multiple of 4, not %i" % len(rawbytes)) + + nvalues = len(rawbytes) / 4 + + values = struct.unpack('>%dI' % nvalues, rawbytes) + encoded = [] + for v in values: + for offset in _85s: + encoded.append(Z85CHARS[(v // offset) % 85]) + + # In Python 3, encoded is a list of integers (obviously?!) + if PY3: + return bytes(encoded) + else: + return b''.join(encoded) + +def decode(z85bytes): + """decode Z85 bytes to raw bytes""" + if len(z85bytes) % 5: + raise ValueError("Z85 length must be multiple of 5, not %i" % len(z85bytes)) + + nvalues = len(z85bytes) / 5 + values = [] + for i in range(0, len(z85bytes), 5): + value = 0 + for j, offset in enumerate(_85s): + value += Z85MAP[z85bytes[i+j]] * offset + values.append(value) + return struct.pack('>%dI' % nvalues, *values) |