From 355a12ff139812658f6775ff0bef4265f8687997 Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Thu, 13 Apr 2017 15:38:58 -0400 Subject: [PATCH] Added string and list parsing --- don/string.py | 69 +++++++++++++++++++++++++++++++++++++++++++++++++-- test_don.py | 28 +++++++++++++++++---- 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/don/string.py b/don/string.py index ee925f6..53551df 100644 --- a/don/string.py +++ b/don/string.py @@ -98,7 +98,7 @@ def _binary32_parser(s): match = _BINARY32_MATCHER.match(s) if match: - # TODO Validate that the double is in range + # TODO Validate that the float is in range return _shared.ParseResult( success = True, value = float(match.group(1)), @@ -126,7 +126,6 @@ def _binary_parser(s): match = _BINARY_MATCHER.match(s) if match: - # TODO Validate that the double is in range return _shared.ParseResult( success = True, value = binascii.unhexlify(match.group(1)), @@ -135,6 +134,67 @@ def _binary_parser(s): return _shared._FAILED_PARSE_RESULT +def _make_utf_parser(encoding): + matcher = re.compile(r'"(.*?)"' + encoding) + + def parser(s): + match = matcher.match(s) + + if match: + return _shared.ParseResult( + success = True, + value = match.group(1), + remaining = s[match.end():], + ) + + return _shared._FAILED_PARSE_RESULT + + return parser + +def _prefix_with_comma(parser): + def wrapped(s): + if s.startswith(','): + s = s[1:] + + result = parser(s) + if not result.success: + raise Exception('Trailing comma before "{}"'.format(s)) + + return result + + return _shared._FAILED_PARSE_RESULT + + return wrapped + +def _list_parser(s): + # TODO Assert they are all the same type + if not s.startswith('['): + return _shared._FAILED_PARSE_RESULT + s = s[1:] + + value = [] + + first = True + parse_result = _object_parser(s) + + while parse_result.success: + value.append(parse_result.value) + s = parse_result.remaining + parse_result = _prefix_with_comma(_object_parser)(s) + + if not s.startswith(']'): + return _shared._FAILED_PARSE_RESULT + + return _shared.ParseResult( + success = True, + value = value, + remaining = s[1:], + ) + + + +def _dictionary_parser(s): + return _shared._FAILED_PARSE_RESULT _PARSERS = [ @@ -148,6 +208,11 @@ _PARSERS = [ _binary32_parser, _binary64_parser, _binary_parser, + _make_utf_parser('utf8'), + _make_utf_parser('utf16'), + _make_utf_parser('utf32'), + _list_parser, + _dictionary_parser, ] def _object_parser(source): diff --git a/test_don.py b/test_don.py index 1b68059..fe46bbc 100644 --- a/test_don.py +++ b/test_don.py @@ -214,16 +214,34 @@ class TestStringDeserialize(unittest.TestCase): def test_deserializes_double(self): self.assertEqual(1.0, string.deserialize('1.0d')) - def test_serializes_binary(self): + def test_deserializes_binary(self): self.assertEqual( b'\xde\xad\xbe\xef', - string.deserialize(b'\x30\x00\x00\x00\x04\xde\xad\xbe\xef'), + string.deserialize('"deadbeef"b'), ) - def test_serializes_binary(self): + def test_deserializes_utf8(self): self.assertEqual( - b'\xde\xad\xbe\xef', - string.deserialize('"deadbeef"b'), + "Hello, world", + string.deserialize('"Hello, world"utf8'), + ) + + def test_deserializes_utf16(self): + self.assertEqual( + "Hello, world", + string.deserialize('"Hello, world"utf16'), + ) + + def test_deserializes_utf32(self): + self.assertEqual( + "Hello, world", + string.deserialize('"Hello, world"utf32'), + ) + + def test_deserializes_list(self): + self.assertEqual( + [1,2,3,4,5], + string.deserialize("[1i8,2i8,3i8,4i8,5i8]"), ) unittest.main() -- 2.20.1