From 5f3192e09981dabf321b10271ea798535ef04484 Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Sat, 24 Sep 2016 16:23:41 -0400 Subject: [PATCH] Added serialization for tag-only types --- serial/binary.py | 51 +++++++++++++++++++++++++++++++++++++++++ serial/test_binary.py | 53 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 serial/binary.py create mode 100644 serial/test_binary.py diff --git a/serial/binary.py b/serial/binary.py new file mode 100644 index 0000000..2b18bfb --- /dev/null +++ b/serial/binary.py @@ -0,0 +1,51 @@ +import collections + +TAG_NULL = 0x00 +TAG_TRUE = 0x01 +TAG_FALSE = 0x02 + +TaggedObject = collections.namedtuple( + 'TaggedObject', + [ + 'tag', + 'instance', + ], +) + +def _make_tag_only_serializer(tag, expected_value): + tag = bytes([tag]) + + def serializer(to): + assert to.instance == expected_value + return tag + + return serializer + +_TAGS_TO_SERIALIZERS = { + TAG_NULL: _make_tag_only_serializer(TAG_NULL, None), + TAG_TRUE: _make_tag_only_serializer(TAG_TRUE, True), + TAG_FALSE: _make_tag_only_serializer(TAG_FALSE, False), +} + +def serialize(to): + return _TAGS_TO_SERIALIZERS[to.tag](to) + +def _make_tag_only_parser(tag, value): + def parser(b): + return TaggedObject(tag = tag, instance = value), b + + return parser + +_TAGS_TO_PARSERS = { + TAG_NULL: _make_tag_only_parser(TAG_NULL, None), + TAG_TRUE: _make_tag_only_parser(TAG_TRUE, True), + TAG_FALSE: _make_tag_only_parser(TAG_FALSE, False), +} + +def deserialize(b): + result, remainder = _TAGS_TO_PARSERS[b[0]](b[1:]) + + if len(remainder) == 0: + return result + + raise Exception('Unable to parse remainder: {}'.format(remainder)) diff --git a/serial/test_binary.py b/serial/test_binary.py new file mode 100644 index 0000000..b9acaa5 --- /dev/null +++ b/serial/test_binary.py @@ -0,0 +1,53 @@ +import unittest + +import binary + +class SerializeTests(unittest.TestCase): + def test_serializes_tag_only_types(self): + self.assertEqual( + binary.serialize(binary.TaggedObject( + tag = binary.TAG_NULL, + instance = None, + )), + b'\x00', + ) + self.assertEqual( + binary.serialize(binary.TaggedObject( + tag = binary.TAG_TRUE, + instance = True, + )), + b'\x01', + ) + self.assertEqual( + binary.serialize(binary.TaggedObject( + tag = binary.TAG_FALSE, + instance = False, + )), + b'\x02', + ) + +class DeserializeTests(unittest.TestCase): + def test_deserializes_tag_only_types(self): + self.assertEqual( + binary.deserialize(b'\x00'), + binary.TaggedObject( + tag = binary.TAG_NULL, + instance = None, + ), + ) + self.assertEqual( + binary.deserialize(b'\x01'), + binary.TaggedObject( + tag = binary.TAG_TRUE, + instance = True, + ), + ) + self.assertEqual( + binary.deserialize(b'\x02'), + binary.TaggedObject( + tag = binary.TAG_FALSE, + instance = False, + ) + ) + +unittest.main() -- 2.20.1