6 def _make_literal_serializer(expected_value, literal):
8 assert to.instance is expected_value
13 def _make_integer_serializer(lower_bound, upper_bound, suffix):
15 assert lower_bound <= to.instance and to.instance < upper_bound
16 return '{}{}'.format(to.instance, suffix)
20 def _make_unsigned_integer_serializer(bit_length):
21 return _make_integer_serializer(0, 2 << (bit_length - 1), 'u{}'.format(bit_length))
23 def _make_signed_integer_serializer(bit_length):
24 upper_bound = 2 << (bit_length - 2)
25 lower_bound = -upper_bound
26 return _make_integer_serializer(lower_bound, upper_bound, 'i{}'.format(bit_length))
28 def _serialize_binary(to):
29 return 'bin"{}"'.format(binascii.hexlify(to.instance).decode('ascii'))
36 def _escape_character(ch):
37 return _ESCAPES.get(ch, ch)
40 return ''.join(_escape_character(ch) for ch in s)
42 def _make_string_serializer(prefix):
44 assert isinstance(to.instance, str)
45 return '{}"{}"'.format(prefix, _escape(to.instance))
49 def _indent(s, depth = 2):
50 return '\n'.join(' ' * depth + line for line in s.split('\n'))
52 def _serialize_list(to):
53 assert isinstance(to.instance, list)
55 return '[\n' + _indent(',\n'.join(serialize(i) for i in to.instance)) + '\n]'
57 def _serialize_key_value_pair(kvp):
58 assert isinstance(kvp, tuple)
61 assert key.tag in [tags.UTF8, tags.UTF16, tags.UTF32]
63 return '{}: {}'.format(serialize(key), serialize(value))
65 def _serialize_object(to):
66 assert isinstance(to.instance, list)
68 return '{\n' + _indent(',\n'.join(_serialize_key_value_pair(kvp) for kvp in to.instance)) + '\n}'
69 raise Exception('Not implemented')
72 tags.NULL: _make_literal_serializer(None, 'null'),
73 tags.TRUE: _make_literal_serializer(True, 'true'),
74 tags.FALSE: _make_literal_serializer(False, 'false'),
75 tags.UINT8: _make_unsigned_integer_serializer(8),
76 tags.UINT16: _make_unsigned_integer_serializer(16),
77 tags.UINT32: _make_unsigned_integer_serializer(32),
78 tags.UINT64: _make_unsigned_integer_serializer(64),
79 tags.INT8: _make_signed_integer_serializer(8),
80 tags.INT16: _make_signed_integer_serializer(16),
81 tags.INT32: _make_signed_integer_serializer(32),
82 tags.INT64: _make_signed_integer_serializer(64),
83 tags.BINARY: _serialize_binary,
84 tags.UTF8: _make_string_serializer('utf8'),
85 tags.UTF16: _make_string_serializer('utf16'),
86 tags.UTF32: _make_string_serializer('utf32'),
87 tags.LIST: _serialize_list,
88 tags.OBJECT: _serialize_object,
92 return _SERIALIZERS[to.tag](to)
94 def _make_literal_deserializer(tag, instance, literal):
96 if s.startswith(literal):
97 return True, tags.TaggedObject(tag = tag, instance = instance), s[len(literal):]
99 return False, None, None
103 def _make_regex_deserializer(tag, decoder, regex):
104 matcher = re.compile(regex).match
106 def _deserializer(s):
110 return False, None, None
112 return True, tags.TaggedObject(tag = tag, instance = decoder(match)), s[match.end():]
116 def _make_unsigned_int_deserializer(tag, bit_length):
117 bound = 2 << (bit_length - 1)
120 result = int(match.group(1))
121 assert result < bound
124 return _make_regex_deserializer(tag, _decoder, r'(\d+)' + 'u{}'.format(bit_length))
126 def _make_signed_int_deserializer(tag, bit_length):
127 upper_bound = 2 << (bit_length - 2)
128 lower_bound = -upper_bound
131 result = int(match.group(1))
132 assert lower_bound <= result and result < upper_bound
135 return _make_regex_deserializer(tag, _decoder, r'(-?\d+)' + 'i{}'.format(bit_length))
137 _BINARY_MATCHER = re.compile(r'bin"([\da-f]*)"').match
139 def _deserialize_binary(s):
140 match = _BINARY_MATCHER(s)
143 return False, None, None
145 result = tags.TaggedObject(
147 instance = binascii.unhexlify(match.group(1)),
150 return True, result, s[match.end():]
152 def _make_string_matcher(prefix):
153 return re.compile(prefix + r'"(([^"]|\\.)*)"').match
155 _UNESCAPE_CHARACTERS = {
160 def _unescape_character(ch):
161 return _UNESCAPE_CHARACTERS[ch]
169 characters.append(_unescape_character(ch))
176 characters.append(ch)
178 return ''.join(characters)
180 def _make_string_deserializer(tag, prefix):
181 matcher = _make_string_matcher(prefix)
187 return False, None, None
189 result = tags.TaggedObject(
191 instance = _unescape(match.group(1)),
194 return True, result, s[match.end():]
198 def _deserialize_list(s):
199 if not s.startswith('['):
200 return False, None, None
206 succeeded, result, s = _deserialize_one(s)
208 # TODO Handle empty lists
211 instance.append(result)
215 while not s.startswith(']'):
216 assert s.startswith(',')
219 succeeded, result, s = _deserialize_one(s)
221 # TODO Handle trailing commas
223 instance.append(result)
226 assert s.startswith(']')
227 return True, tags.TaggedObject(tag = tags.LIST, instance = instance), s[1:]
229 def _deserialize_object(s):
230 if not s.startswith('{'):
231 return False, None, None
237 # TODO Handle empty objects
239 succeeded, key, s = _deserialize_one(s)
242 assert key.tag in [tags.UTF8, tags.UTF16, tags.UTF32]
245 assert s.startswith(':')
249 succeeded, value, s = _deserialize_one(s)
252 instance.append((key, value))
256 while s.startswith(','):
257 succeeded, key, s = _deserialize_one(s)
260 assert key.tag in [tags.UTF8, tags.UTF16, tags.UTF32]
263 assert s.startswith(':')
267 succeeded, value, s = _deserialize_one(s)
270 instance.append((key, value))
274 assert s.startswith('}')
275 return True, tags.TaggedObject(tag = tags.LIST, instance = instance), s[1:]
278 _make_literal_deserializer(tags.NULL, None, 'null'),
279 _make_literal_deserializer(tags.TRUE, True, 'true'),
280 _make_literal_deserializer(tags.FALSE, False, 'false'),
281 _make_unsigned_int_deserializer(tags.UINT8, 8),
282 _make_unsigned_int_deserializer(tags.UINT16, 16),
283 _make_unsigned_int_deserializer(tags.UINT32, 32),
284 _make_unsigned_int_deserializer(tags.UINT64, 64),
285 _make_signed_int_deserializer(tags.INT8, 8),
286 _make_signed_int_deserializer(tags.INT16, 16),
287 _make_signed_int_deserializer(tags.INT32, 32),
288 _make_signed_int_deserializer(tags.INT64, 64),
290 _make_string_deserializer(tags.UTF8, 'utf8'),
291 _make_string_deserializer(tags.UTF16, 'utf16'),
292 _make_string_deserializer(tags.UTF32, 'utf32'),
297 def _deserialize_one(s):
300 for deserializer in _DESERIALIZERS:
301 succeeded, result, remaining = deserializer(s)
304 return succeeded, result, remaining
306 return False, None, None
309 succeeded, result, remaining = _deserialize_one(s)
312 assert remaining == ''