20 DEFAULT_INTEGER_ENCODING = INT32
21 DEFAULT_DECIMAL_ENCODING = DOUBLE
22 DEFAULT_STRING_ENCODING = UTF8
24 TaggedObject = collections.namedtuple('TaggedObject', ['tag', 'value'])
27 int: DEFAULT_INTEGER_ENCODING,
28 float: DEFAULT_DECIMAL_ENCODING,
30 str: DEFAULT_STRING_ENCODING,
33 collections.OrderedDict: DICTIONARY,
37 if isinstance(o, TaggedObject):
41 return TaggedObject(tag = VOID, value = o)
44 return TaggedObject(tag = TRUE, value = o)
47 return TaggedObject(tag = FALSE, value = o)
49 return TaggedObject(tag = _TYPES_TO_TAGS[type(o)], value = o)
51 _NONE = TaggedObject(tag = VOID, value = None)
52 _TRUE = TaggedObject(tag = TRUE, value = True)
53 _FALSE = TaggedObject(tag = FALSE, value = False)
55 _TAGS_TO_IN_RANGE_PREDICATES = collections.OrderedDict([
56 (INT8, lambda i: -128 <= i and i <= 127),
57 (INT16, lambda i: -32768 <= i and i <= 32767),
58 (INT32, lambda i: -2147483648 <= i and i <= 2147483647),
59 (INT64, lambda i: -9223372036854775808 <= i and i <= 9223372036854775807),
62 class TooWideError(Exception):
67 def autotag(o, **kwargs):
68 preferred_integer_tag = kwargs.pop('preferred_integer_tag', DEFAULT_INTEGER_ENCODING)
69 preferred_string_tag = kwargs.pop('preferred_string_tag', DEFAULT_STRING_ENCODING)
72 raise TypeError("autotag() got an unexpected keyword argument '{}'".format(
73 list(kwargs.keys())[0],
76 if isinstance(o, TaggedObject):
88 if isinstance(o, int):
89 if preferred_integer_tag is not SMALLEST and _TAGS_TO_IN_RANGE_PREDICATES[preferred_integer_tag](o):
90 return TaggedObject(tag = preferred_integer_tag, value = o)
93 for tag, in_range_predicate in _TAGS_TO_IN_RANGE_PREDICATES.items():
94 if in_range_predicate(o):
95 return TaggedObject(tag = tag, value = o)
97 raise TooWideError("Integer {} is too wide to be serialized")
99 if isinstance(o, float):
100 raise Exception('Unsupported type {}'.format(type(o)))
102 if isinstance(o, str):
103 # TODO Support SMALLEST for preferred string tag
104 return TaggedObject(tag = preferred_string_tag, value = o)
106 if isinstance(o, list):
112 preferred_integer_tag = preferred_integer_tag,
113 preferred_string_tag = preferred_string_tag,
118 if isinstance(o, dict):
121 value = collections.OrderedDict([
125 preferred_integer_tag = preferred_integer_tag,
126 preferred_string_tag = preferred_string_tag,
130 preferred_integer_tag = preferred_integer_tag,
131 preferred_string_tag = preferred_string_tag,
133 ) for key, value in o.items()
137 raise Exception('Unsupported type {}'.format(type(o)))