Mercurial > public > mercurial-scm > hg
diff mercurial/thirdparty/cbor/cbor2/compat.py @ 37126:4bd73a955ab0
thirdparty: vendor cbor2 python library
CBOR stands for Concise Binary Object Representation, which is a data format
which is very compact and extensible.
This patch moves the python library which can serilaize and deserialize python
objects to/from cbor formats. The library is taken from
https://github.com/agronholm/cbor2/ from commit
84181540f6eb650437e3f73cd104a65661fe8e67.
Unrequired files from the cbor library - docs/, tests/, setup.py, setup.cfg,
and tox.ini - have not been vendored.
There is another python library for cbor at
https://github.com/brianolson/cbor_py/ which is used in evolve extension and was
imported in initial version of this series. That library though contains C code
and is bit faster, but has known bugs around serializing nested structures, is
unmaintained, raises an Exception object instead of a more dedicated Error type.
So, it's better to use a bug free and actively maintained library.
This library is not yet used and will be used in later commits.
# no-check-commit because we are importing a third library module
Differential Revision: https://phab.mercurial-scm.org/D2750
author | Pulkit Goyal <7895pulkit@gmail.com> |
---|---|
date | Mon, 26 Mar 2018 08:33:57 -0700 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/thirdparty/cbor/cbor2/compat.py Mon Mar 26 08:33:57 2018 -0700 @@ -0,0 +1,101 @@ +from math import ldexp +import struct +import sys + + +if sys.version_info.major < 3: + from datetime import tzinfo, timedelta + + class timezone(tzinfo): + def __init__(self, offset): + self.offset = offset + + def utcoffset(self, dt): + return self.offset + + def dst(self, dt): + return timedelta(0) + + def tzname(self, dt): + return 'UTC+00:00' + + def as_unicode(string): + return string.decode('utf-8') + + def iteritems(self): + return self.iteritems() + + def bytes_from_list(values): + return bytes(bytearray(values)) + + byte_as_integer = ord + timezone.utc = timezone(timedelta(0)) + xrange = xrange # noqa: F821 + long = long # noqa: F821 + unicode = unicode # noqa: F821 +else: + from datetime import timezone + + def byte_as_integer(bytestr): + return bytestr[0] + + def as_unicode(string): + return string + + def iteritems(self): + return self.items() + + xrange = range + long = int + unicode = str + bytes_from_list = bytes + + +if sys.version_info.major >= 3 and sys.version_info.minor >= 6: + # Python 3.6 added 16 bit floating point to struct + + def pack_float16(value): + try: + return struct.pack('>Be', 0xf9, value) + except OverflowError: + return False + + def unpack_float16(payload): + return struct.unpack('>e', payload)[0] +else: + def pack_float16(value): + # Based on node-cbor by hildjj + # which was based in turn on Carsten Borman's cn-cbor + u32 = struct.pack('>f', value) + u = struct.unpack('>I', u32)[0] + + if u & 0x1FFF != 0: + return False + + s16 = (u >> 16) & 0x8000 + exponent = (u >> 23) & 0xff + mantissa = u & 0x7fffff + + if 113 <= exponent <= 142: + s16 += ((exponent - 112) << 10) + (mantissa >> 13) + elif 103 <= exponent < 113: + if mantissa & ((1 << (126 - exponent)) - 1): + return False + + s16 += ((mantissa + 0x800000) >> (126 - exponent)) + else: + return False + + return struct.pack('>BH', 0xf9, s16) + + def unpack_float16(payload): + # Code adapted from RFC 7049, appendix D + def decode_single(single): + return struct.unpack("!f", struct.pack("!I", single))[0] + + payload = struct.unpack('>H', payload)[0] + value = (payload & 0x7fff) << 13 | (payload & 0x8000) << 16 + if payload & 0x7c00 != 0x7c00: + return ldexp(decode_single(value), 112) + + return decode_single(value | 0x7f800000)