e8c9093d71f29cad1d2445a4b63ffba6b3c689f7
[sandbox] / serial / binary.py
1 import collections
2 import io
3
4 TAG_NULL = 0x00
5 TAG_TRUE = 0x01
6 TAG_FALSE = 0x02
7
8 TaggedObject = collections.namedtuple(
9     'TaggedObject',
10     [
11         'tag',
12         'instance',
13     ],
14 )
15
16 def _make_tag_only_serializer(tag, expected_value):
17     tag = bytes([tag])
18
19     def serializer(to):
20         assert to.instance == expected_value
21         return tag
22
23     return serializer
24
25 _TAGS_TO_SERIALIZERS = {
26     TAG_NULL: _make_tag_only_serializer(TAG_NULL, None),
27     TAG_TRUE: _make_tag_only_serializer(TAG_TRUE, True),
28     TAG_FALSE: _make_tag_only_serializer(TAG_FALSE, False),
29 }
30
31 def serialize(to):
32     return _TAGS_TO_SERIALIZERS[to.tag](to)
33
34 def _make_tag_only_parser(tag, value):
35     def parser(b):
36         return TaggedObject(tag = tag, instance = value)
37
38     return parser
39
40 _TAGS_TO_PARSERS = {
41     TAG_NULL: _make_tag_only_parser(TAG_NULL, None),
42     TAG_TRUE: _make_tag_only_parser(TAG_TRUE, True),
43     TAG_FALSE: _make_tag_only_parser(TAG_FALSE, False),
44 }
45
46 def deserialize(b):
47     if isinstance(b, bytes):
48         b = io.BytesIO(b)
49
50     tag = b.read(1)[0]
51
52     result = _TAGS_TO_PARSERS[tag](b)
53
54     remainder = b.read()
55
56     if len(remainder) == 0:
57         return result
58
59     raise Exception('Unable to parse remainder: {}'.format(remainder))