Parse constants and integers with leading whitespace
authorDavid Kerkeslager <kerkeslager@gmail.com>
Fri, 14 Apr 2017 15:46:42 +0000 (11:46 -0400)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Fri, 14 Apr 2017 15:46:42 +0000 (11:46 -0400)
don/string.py
test_don.py

index e22b328..1e930ac 100644 (file)
@@ -1,5 +1,6 @@
 import binascii
 import collections
+import functools
 import re
 
 from don import tags, _shared
@@ -60,8 +61,17 @@ def serialize(o):
     
     return _STRING_SERIALIZERS[o.tag](o.value)
 
-def _make_constant_parser(constant, value):
+def _consume_leading_whitespace(wrapped_parser):
+    @functools.wraps(wrapped_parser)
     def parser(s):
+        s = s.lstrip()
+        return wrapped_parser(s)
+
+    return parser
+
+def _make_constant_parser(constant, value):
+    @_consume_leading_whitespace
+    def constant_parser(s):
         if s.startswith(constant):
             result = _shared.ParseResult(
                 success = True,
@@ -72,12 +82,13 @@ def _make_constant_parser(constant, value):
 
         return _shared._FAILED_PARSE_RESULT
 
-    return parser
+    return constant_parser
 
 def _make_integer_parser(width):
     matcher = re.compile(r'(-?\d+)i' + str(width))
 
-    def parser(s):
+    @_consume_leading_whitespace
+    def integer_parser(s):
         match = matcher.match(s)
 
         if match:
@@ -90,7 +101,7 @@ def _make_integer_parser(width):
 
         return _shared._FAILED_PARSE_RESULT
 
-    return parser
+    return integer_parser
 
 _BINARY32_MATCHER = re.compile(r'(-?\d+\.\d+)f')
 _BINARY64_MATCHER = re.compile(r'(-?\d+\.\d+)d')
index c4e9549..df62ff5 100644 (file)
@@ -180,34 +180,68 @@ class TestStringDeserialize(unittest.TestCase):
             string.deserialize('null'),
         )
 
-    def test_deserializes_null(self):
+    def test_deserializes_null_with_leading_whitespace(self):
+        self.assertEqual(
+            None,
+            string.deserialize(' \t\nnull'),
+        )
+
+    def test_deserializes_true(self):
         self.assertEqual(
             True,
             string.deserialize('true'),
         )
 
-    def test_deserializes_null(self):
+    def test_deserializes_true_with_leading_whitespace(self):
+        self.assertEqual(
+            True,
+            string.deserialize(' \t\ntrue'),
+        )
+
+    def test_deserializes_false(self):
         self.assertEqual(
             False,
             string.deserialize('false'),
         )
 
+    def test_deserializes_false_with_leading_whitespace(self):
+        self.assertEqual(
+            False,
+            string.deserialize(' \t\nfalse'),
+        )
+
     def test_deserializes_int8(self):
         self.assertEqual(10, string.deserialize('10i8'))
         self.assertEqual(-1, string.deserialize('-1i8'))
 
+    def test_deserializes_int8_with_leading_whitespace(self):
+        self.assertEqual(10, string.deserialize(' \t\n10i8'))
+        self.assertEqual(-1, string.deserialize(' \t\n-1i8'))
+
     def test_deserializes_int16(self):
         self.assertEqual(10, string.deserialize('10i16'))
         self.assertEqual(-1, string.deserialize('-1i16'))
 
+    def test_deserializes_int16_with_leading_whitespace(self):
+        self.assertEqual(10, string.deserialize(' \t\n10i16'))
+        self.assertEqual(-1, string.deserialize(' \t\n-1i16'))
+
     def test_deserializes_int32(self):
         self.assertEqual(10, string.deserialize('10i32'))
         self.assertEqual(-1, string.deserialize('-1i32'))
 
+    def test_deserializes_int32_with_leading_whitespace(self):
+        self.assertEqual(10, string.deserialize(' \t\n10i32'))
+        self.assertEqual(-1, string.deserialize(' \t\n-1i32'))
+
     def test_deserializes_int64(self):
         self.assertEqual(10, string.deserialize('10i64'))
         self.assertEqual(-1, string.deserialize('-1i64'))
 
+    def test_deserializes_int64_with_leading_whitespace(self):
+        self.assertEqual(10, string.deserialize(' \t\n10i64'))
+        self.assertEqual(-1, string.deserialize(' \t\n-1i64'))
+
     def test_deserializes_float(self):
         self.assertEqual(1.0, string.deserialize('1.0f'))