From 1e8e6816c9f74de6cb6ab735fc962c7dc8b67164 Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Sat, 24 Sep 2016 19:03:32 -0400 Subject: [PATCH] Added string serialization/deserialization --- serial/binary.py | 36 ++++++++++++++++++++++++++++++++++++ serial/test_binary.py | 4 ++++ 2 files changed, 40 insertions(+) diff --git a/serial/binary.py b/serial/binary.py index d362092..7ce58b7 100644 --- a/serial/binary.py +++ b/serial/binary.py @@ -14,6 +14,10 @@ TAG_INT8 = 0x10 TAG_INT16 = 0x11 TAG_INT32 = 0x12 TAG_INT64 = 0x13 +TAG_BINARY = 0x20 +TAG_UTF8 = 0x21 +TAG_UTF16 = 0x22 +TAG_UTF32 = 0x23 TaggedObject = collections.namedtuple( 'TaggedObject', @@ -41,6 +45,15 @@ def _make_struct_serializer(fmt): return serializer +def _make_string_serializer(encoder): + packer = functools.partial(struct.pack, '!BI') + + def serializer(to): + encoded = encoder(to.instance) + return packer(to.tag, len(encoded)) + encoded + + return serializer + _TAGS_TO_SERIALIZERS = { TAG_NULL: _make_tag_only_serializer(TAG_NULL, None), TAG_TRUE: _make_tag_only_serializer(TAG_TRUE, True), @@ -53,6 +66,10 @@ _TAGS_TO_SERIALIZERS = { TAG_INT16: _make_struct_serializer('h'), TAG_INT32: _make_struct_serializer('i'), TAG_INT64: _make_struct_serializer('q'), + TAG_BINARY: _make_string_serializer(lambda s: s), + TAG_UTF8: _make_string_serializer(lambda s: s.encode('utf-8')), + TAG_UTF16: _make_string_serializer(lambda s: s.encode('utf-16')), + TAG_UTF32: _make_string_serializer(lambda s: s.encode('utf-32')), } def serialize(to): @@ -76,6 +93,21 @@ def _make_struct_deserializer(tag, fmt): return parser +def _make_string_deserializer(tag, decoder): + fmt = '!I' + size = struct.calcsize(fmt) + unpacker = functools.partial(struct.unpack, fmt) + + def parser(b): + length_b = b.read(size) + assert len(length_b) == size + length = unpacker(length_b)[0] + s = b.read(length) + assert len(s) == length + return TaggedObject(tag = tag, instance = decoder(s)) + + return parser + _TAGS_TO_PARSERS = { TAG_NULL: _make_tag_only_parser(TAG_NULL, None), TAG_TRUE: _make_tag_only_parser(TAG_TRUE, True), @@ -88,6 +120,10 @@ _TAGS_TO_PARSERS = { TAG_INT16: _make_struct_deserializer(TAG_INT16, 'h'), TAG_INT32: _make_struct_deserializer(TAG_INT32, 'i'), TAG_INT64: _make_struct_deserializer(TAG_INT64, 'q'), + TAG_BINARY: _make_string_deserializer(TAG_BINARY, lambda b: b), + TAG_UTF8: _make_string_deserializer(TAG_UTF8, lambda b: b.decode('utf-8')), + TAG_UTF16: _make_string_deserializer(TAG_UTF16, lambda b: b.decode('utf-16')), + TAG_UTF32: _make_string_deserializer(TAG_UTF32, lambda b: b.decode('utf-32')), } def deserialize(b): diff --git a/serial/test_binary.py b/serial/test_binary.py index 0463dda..8bc3811 100644 --- a/serial/test_binary.py +++ b/serial/test_binary.py @@ -22,6 +22,10 @@ EXAMPLE_REPRESENTATIONS = [ (binary.TAG_INT16, -2, b'\x11\xff\xfe'), (binary.TAG_INT32, -2, b'\x12\xff\xff\xff\xfe'), (binary.TAG_INT64, -2, b'\x13\xff\xff\xff\xff\xff\xff\xff\xfe'), + (binary.TAG_BINARY, b'\xde\xad\xbe\xef', b'\x20\x00\x00\x00\x04\xde\xad\xbe\xef'), + (binary.TAG_UTF8, 'Lol!', b'\x21\x00\x00\x00\x04Lol!'), + (binary.TAG_UTF16, 'かわ', b'\x22\x00\x00\x00\x06\xff\xfeK0\x8f0'), + (binary.TAG_UTF32, '漢', b'\x23\x00\x00\x00\x08\xff\xfe\x00\x00"o\x00\x00'), ] class SerializeTests(unittest.TestCase): -- 2.20.1