|
|
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)
|
|
|
|