Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r65964:c6a81f72894e
Date: 2013-08-06 12:24 +0200
http://bitbucket.org/pypy/pypy/changeset/c6a81f72894e/

Log:    rmarshal: support dicts

diff --git a/rpython/rlib/rmarshal.py b/rpython/rlib/rmarshal.py
--- a/rpython/rlib/rmarshal.py
+++ b/rpython/rlib/rmarshal.py
@@ -77,6 +77,7 @@
 TYPE_STRING   = 's'
 TYPE_TUPLE    = '('
 TYPE_LIST     = '['
+TYPE_DICT     = '{'
 
 dumpers = []
 loaders = []
@@ -302,6 +303,12 @@
     loader.pos = pos + 1
     return loader.buf[pos]
 
+def peekchr(loader):
+    pos = loader.pos
+    while pos >= len(loader.buf):
+        loader.need_more_data()
+    return loader.buf[pos]
+
 def readlong(loader):
     a = ord(readchr(loader))
     b = ord(readchr(loader))
@@ -398,6 +405,51 @@
         add_loader(s_list, load_list_or_none)
 
 
+class __extend__(pairtype(MTag, annmodel.SomeDict)):
+
+    def install_marshaller((tag, s_dict)):
+        def dump_dict_or_none(buf, x):
+            if x is None:
+                dump_none(buf, x)
+            else:
+                buf.append(TYPE_DICT)
+                for key, value in x.items():
+                    keydumper(buf, key)
+                    valuedumper(buf, value)
+                buf.append('0')    # end of dict
+
+        keydumper = get_marshaller(s_dict.dictdef.dictkey.s_value)
+        valuedumper = get_marshaller(s_dict.dictdef.dictvalue.s_value)
+        if (s_dict.dictdef.dictkey.dont_change_any_more or
+            s_dict.dictdef.dictvalue.dont_change_any_more):
+            s_general_dict = s_dict
+        else:
+            s_key = get_dumper_annotation(keydumper)
+            s_value = get_dumper_annotation(valuedumper)
+            s_general_dict = annotation({s_key: s_value})
+        add_dumper(s_general_dict, dump_dict_or_none)
+
+    def install_unmarshaller((tag, s_dict)):
+        def load_dict_or_none(loader):
+            t = readchr(loader)
+            if t == TYPE_DICT:
+                result = {}
+                while peekchr(loader) != '0':
+                    key = keyloader(loader)
+                    value = valueloader(loader)
+                    result[key] = value
+                readchr(loader)   # consume the final '0'
+                return result
+            elif t == TYPE_NONE:
+                return None
+            else:
+                raise ValueError("expected a dict or None")
+
+        keyloader = get_loader(s_dict.dictdef.dictkey.s_value)
+        valueloader = get_loader(s_dict.dictdef.dictvalue.s_value)
+        add_loader(s_dict, load_dict_or_none)
+
+
 class __extend__(pairtype(MTag, annmodel.SomeTuple)):
 
     def install_marshaller((tag, s_tuple)):
diff --git a/rpython/rlib/test/test_rmarshal.py 
b/rpython/rlib/test/test_rmarshal.py
--- a/rpython/rlib/test/test_rmarshal.py
+++ b/rpython/rlib/test/test_rmarshal.py
@@ -9,6 +9,7 @@
     [int],
     annmodel.SomeString(can_be_None=True),
     annmodel.s_None,
+    {int: int},
     ]
 
 
@@ -58,6 +59,10 @@
     get_marshaller((int, float, (str, ())))(buf, (7, -1.5, ("foo", ())))
     assert marshal.loads(''.join(buf)) == (7, -1.5, ("foo", ()))
 
+    buf = []
+    get_marshaller({int: str})(buf, {2: "foo", -3: "bar"})
+    assert marshal.loads(''.join(buf)) == {2: "foo", -3: "bar"}
+
     for typ in types_that_can_be_none:
         buf = []
         get_marshaller(typ)(buf, None)
@@ -111,6 +116,11 @@
     res = get_unmarshaller((int, (str, ())))(buf)
     assert res == (7, ("foo", ()))
 
+    buf = ('{i\xfb\xff\xff\xffs\x03\x00\x00\x00bar'
+           'i\x06\x00\x00\x00s\x00\x00\x00\x000')
+    res = get_unmarshaller({int: str})(buf)
+    assert res == {-5: "bar", 6: ""}
+
     for typ in types_that_can_be_none:
         buf = 'N'
         assert get_unmarshaller(typ)(buf) is None
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to