15ffc1027b3e744807fec97b82ac148eab857e92
[ton] / don / string.py
1 import binascii
2
3 from don import tags, _shared
4
5 def _integer_size_to_string_serializer(integer_size):
6     minimum = -(2 ** (integer_size - 1))
7     maximum = 2 ** (integer_size - 1) - 1
8     
9     def serializer(integer):
10         assert minimum <= integer and integer <= maximum
11         return '{}i{}'.format(integer, integer_size)
12
13     return serializer
14
15 def _serialize_float(f):
16     return '{}f'.format(f)
17
18 def _serialize_double(d):
19     return '{}d'.format(d)
20
21 def _serialize_binary(b):
22     return '"{}"b'.format(binascii.hexlify(b).decode('ascii'))
23
24 def _utf_encoding_to_serializer(utf_encoding):
25     def serializer(s):
26         return '"{}"{}'.format(s, utf_encoding)
27
28     return serializer
29
30 def _string_serialize_list(l):
31     return '[{}]'.format(', '.join(map(serialize, l)))
32
33 def _string_serialize_dictionary(d):
34     def serialize_kvp(kvp):
35         return serialize(kvp[0]) + ': ' + serialize(kvp[1])
36     return '{ ' + ', '.join(map(serialize_kvp, d.items())) + ' }'
37
38 _STRING_SERIALIZERS = {
39     tags.VOID: lambda o: 'null',
40     tags.TRUE: lambda o: 'true',
41     tags.FALSE: lambda o: 'false',
42     tags.INT8: _integer_size_to_string_serializer(8),
43     tags.INT16: _integer_size_to_string_serializer(16),
44     tags.INT32: _integer_size_to_string_serializer(32),
45     tags.INT64: _integer_size_to_string_serializer(64),
46     tags.FLOAT: _serialize_float,
47     tags.DOUBLE: _serialize_double,
48     tags.BINARY: _serialize_binary,
49     tags.UTF8: _utf_encoding_to_serializer('utf8'),
50     tags.UTF16: _utf_encoding_to_serializer('utf16'),
51     tags.UTF32: _utf_encoding_to_serializer('utf32'),
52     tags.LIST: _string_serialize_list,
53     tags.DICTIONARY: _string_serialize_dictionary,
54 }
55
56 def serialize(o):
57     o = tags._tag(o)
58     
59     return _STRING_SERIALIZERS[o.tag](o.value)
60
61 def _make_constant_parser(constant, value):
62     def parser(s):
63         if s.startswith(constant):
64             result = _shared.ParseResult(
65                 success = True,
66                 value = value,
67                 remaining = s[len(constant):],
68             )
69             return result
70
71         return _shared._FAILED_PARSE_RESULT
72
73     return parser
74
75 _PARSERS = [
76     _make_constant_parser('null', None),
77     _make_constant_parser('true', True),
78     _make_constant_parser('false', False),
79 ]
80
81 def _object_parser(source):
82     for parser in _PARSERS:
83         result = parser(source)
84
85         if result.success:
86             return result
87
88     return _shared._FAILED_PARSE_RESULT
89
90 def _parse(parser, source):
91     result = parser(source)
92
93     if result.success and result.remaining.strip() == '':
94         return result.value
95
96     raise Exception('Unparsed trailing characters: "{}"'.format(result.remaining))
97
98 def deserialize(s):
99     return _parse(_object_parser, s)