11 # These are to be supported in the future
21 STRING_TAGS = set([UTF8, UTF16, UTF32])
23 DEFAULT_INTEGER_ENCODING = INT32
24 DEFAULT_STRING_ENCODING = UTF8
26 TaggedObject = collections.namedtuple('TaggedObject', ['tag', 'value'])
29 int: DEFAULT_INTEGER_ENCODING,
31 str: DEFAULT_STRING_ENCODING,
34 collections.OrderedDict: DICTIONARY,
38 if isinstance(o, TaggedObject):
42 return TaggedObject(tag = VOID, value = o)
45 return TaggedObject(tag = TRUE, value = o)
48 return TaggedObject(tag = FALSE, value = o)
50 return TaggedObject(tag = _TYPES_TO_TAGS[type(o)], value = o)
52 _NONE = TaggedObject(tag = VOID, value = None)
53 _TRUE = TaggedObject(tag = TRUE, value = True)
54 _FALSE = TaggedObject(tag = FALSE, value = False)
56 _TAGS_TO_IN_RANGE_PREDICATES = collections.OrderedDict([
57 (INT8, lambda i: -128 <= i and i <= 127),
58 (INT16, lambda i: -32768 <= i and i <= 32767),
59 (INT32, lambda i: -2147483648 <= i and i <= 2147483647),
60 (INT64, lambda i: -9223372036854775808 <= i and i <= 9223372036854775807),
63 class TooWideError(Exception):
68 def autotag(o, **kwargs):
69 preferred_integer_tag = kwargs.pop('preferred_integer_tag', DEFAULT_INTEGER_ENCODING)
70 preferred_string_tag = kwargs.pop('preferred_string_tag', DEFAULT_STRING_ENCODING)
73 raise TypeError("autotag() got an unexpected keyword argument '{}'".format(
74 list(kwargs.keys())[0],
77 if isinstance(o, TaggedObject):
89 if isinstance(o, int):
90 if preferred_integer_tag is not SMALLEST and _TAGS_TO_IN_RANGE_PREDICATES[preferred_integer_tag](o):
91 return TaggedObject(tag = preferred_integer_tag, value = o)
94 for tag, in_range_predicate in _TAGS_TO_IN_RANGE_PREDICATES.items():
95 if in_range_predicate(o):
96 return TaggedObject(tag = tag, value = o)
98 raise TooWideError("Integer {} is too wide to be serialized")
100 if isinstance(o, str):
101 # TODO Support SMALLEST for preferred string tag
102 return TaggedObject(tag = preferred_string_tag, value = o)
104 if isinstance(o, bytes):
105 return TaggedObject(tag = BINARY, value = o)
107 if isinstance(o, list):
113 preferred_integer_tag = preferred_integer_tag,
114 preferred_string_tag = preferred_string_tag,
119 if isinstance(o, dict):
122 value = collections.OrderedDict([
126 preferred_integer_tag = preferred_integer_tag,
127 preferred_string_tag = preferred_string_tag,
131 preferred_integer_tag = preferred_integer_tag,
132 preferred_string_tag = preferred_string_tag,
134 ) for key, value in o.items()
138 raise Exception('Unsupported type {}'.format(type(o)))