about summary refs log tree commit diff
path: root/src/libstd/json.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/json.rs')
-rw-r--r--src/libstd/json.rs667
1 files changed, 354 insertions, 313 deletions
diff --git a/src/libstd/json.rs b/src/libstd/json.rs
index 190d2d3fe0b..e090d6bc036 100644
--- a/src/libstd/json.rs
+++ b/src/libstd/json.rs
@@ -105,20 +105,10 @@ impl serialize::Encoder for Encoder {
         self.wr.write_str(float::to_str_digits(v, 6u));
     }
 
-    fn emit_char(&self, v: char) { self.emit_borrowed_str(str::from_char(v)) }
-
-    fn emit_borrowed_str(&self, v: &str) { self.wr.write_str(escape_str(v)) }
-    fn emit_owned_str(&self, v: &str) { self.emit_borrowed_str(v) }
-    fn emit_managed_str(&self, v: &str) { self.emit_borrowed_str(v) }
-
-    fn emit_borrowed(&self, f: &fn()) { f() }
-    fn emit_owned(&self, f: &fn()) { f() }
-    fn emit_managed(&self, f: &fn()) { f() }
-
-    fn emit_enum(&self, _name: &str, f: &fn()) {
-        f()
-    }
+    fn emit_char(&self, v: char) { self.emit_str(str::from_char(v)) }
+    fn emit_str(&self, v: &str) { self.wr.write_str(escape_str(v)) }
 
+    fn emit_enum(&self, _name: &str, f: &fn()) { f() }
     fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
         // enums are encoded as strings or vectors:
         // Bunny => "Bunny"
@@ -140,28 +130,17 @@ impl serialize::Encoder for Encoder {
         f();
     }
 
-    fn emit_borrowed_vec(&self, _len: uint, f: &fn()) {
+    fn emit_seq(&self, _len: uint, f: &fn()) {
         self.wr.write_char('[');
         f();
         self.wr.write_char(']');
     }
 
-    fn emit_owned_vec(&self, len: uint, f: &fn()) {
-        self.emit_borrowed_vec(len, f)
-    }
-    fn emit_managed_vec(&self, len: uint, f: &fn()) {
-        self.emit_borrowed_vec(len, f)
-    }
-    fn emit_vec_elt(&self, idx: uint, f: &fn()) {
+    fn emit_seq_elt(&self, idx: uint, f: &fn()) {
         if idx != 0 { self.wr.write_char(','); }
         f()
     }
 
-    fn emit_rec(&self, f: &fn()) {
-        self.wr.write_char('{');
-        f();
-        self.wr.write_char('}');
-    }
     fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) {
         self.wr.write_char('{');
         f();
@@ -174,16 +153,25 @@ impl serialize::Encoder for Encoder {
         f();
     }
 
-    fn emit_tup(&self, len: uint, f: &fn()) {
-        self.emit_borrowed_vec(len, f);
-    }
-    fn emit_tup_elt(&self, idx: uint, f: &fn()) {
-        self.emit_vec_elt(idx, f)
-    }
-
     fn emit_option(&self, f: &fn()) { f(); }
     fn emit_option_none(&self) { self.emit_nil(); }
     fn emit_option_some(&self, f: &fn()) { f(); }
+
+    fn emit_map(&self, _len: uint, f: &fn()) {
+        self.wr.write_char('{');
+        f();
+        self.wr.write_char('}');
+    }
+
+    fn emit_map_elt_key(&self, idx: uint, f: &fn()) {
+        if idx != 0 { self.wr.write_char(','); }
+        f()
+    }
+
+    fn emit_map_elt_val(&self, _idx: uint, f: &fn()) {
+        self.wr.write_char(':');
+        f()
+    }
 }
 
 pub struct PrettyEncoder {
@@ -224,15 +212,8 @@ impl serialize::Encoder for PrettyEncoder {
         self.wr.write_str(float::to_str_digits(v, 6u));
     }
 
-    fn emit_char(&self, v: char) { self.emit_borrowed_str(str::from_char(v)) }
-
-    fn emit_borrowed_str(&self, v: &str) { self.wr.write_str(escape_str(v)); }
-    fn emit_owned_str(&self, v: &str) { self.emit_borrowed_str(v) }
-    fn emit_managed_str(&self, v: &str) { self.emit_borrowed_str(v) }
-
-    fn emit_borrowed(&self, f: &fn()) { f() }
-    fn emit_owned(&self, f: &fn()) { f() }
-    fn emit_managed(&self, f: &fn()) { f() }
+    fn emit_char(&self, v: char) { self.emit_str(str::from_char(v)) }
+    fn emit_str(&self, v: &str) { self.wr.write_str(escape_str(v)); }
 
     fn emit_enum(&self, _name: &str, f: &fn()) { f() }
     fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
@@ -260,7 +241,7 @@ impl serialize::Encoder for PrettyEncoder {
         f()
     }
 
-    fn emit_borrowed_vec(&self, len: uint, f: &fn()) {
+    fn emit_seq(&self, len: uint, f: &fn()) {
         if len == 0 {
             self.wr.write_str("[]");
         } else {
@@ -273,13 +254,7 @@ impl serialize::Encoder for PrettyEncoder {
             self.wr.write_char(']');
         }
     }
-    fn emit_owned_vec(&self, len: uint, f: &fn()) {
-        self.emit_borrowed_vec(len, f)
-    }
-    fn emit_managed_vec(&self, len: uint, f: &fn()) {
-        self.emit_borrowed_vec(len, f)
-    }
-    fn emit_vec_elt(&self, idx: uint, f: &fn()) {
+    fn emit_seq_elt(&self, idx: uint, f: &fn()) {
         if idx == 0 {
             self.wr.write_char('\n');
         } else {
@@ -289,20 +264,17 @@ impl serialize::Encoder for PrettyEncoder {
         f()
     }
 
-    fn emit_rec(&self, f: &fn()) {
-        self.wr.write_char('{');
-        self.indent += 2;
-        f();
-        self.wr.write_char('\n');
-        self.indent -= 2;
-        self.wr.write_str(spaces(self.indent));
-        self.wr.write_char('}');
-    }
     fn emit_struct(&self, _name: &str, len: uint, f: &fn()) {
         if len == 0 {
             self.wr.write_str("{}");
         } else {
-            self.emit_rec(f)
+            self.wr.write_char('{');
+            self.indent += 2;
+            f();
+            self.wr.write_char('\n');
+            self.indent -= 2;
+            self.wr.write_str(spaces(self.indent));
+            self.wr.write_char('}');
         }
     }
     fn emit_field(&self, name: &str, idx: uint, f: &fn()) {
@@ -316,37 +288,49 @@ impl serialize::Encoder for PrettyEncoder {
         self.wr.write_str(": ");
         f();
     }
-    fn emit_tup(&self, sz: uint, f: &fn()) {
-        self.emit_borrowed_vec(sz, f);
-    }
-    fn emit_tup_elt(&self, idx: uint, f: &fn()) {
-        self.emit_vec_elt(idx, f)
-    }
 
     fn emit_option(&self, f: &fn()) { f(); }
     fn emit_option_none(&self) { self.emit_nil(); }
     fn emit_option_some(&self, f: &fn()) { f(); }
+
+    fn emit_map(&self, len: uint, f: &fn()) {
+        if len == 0 {
+            self.wr.write_str("{}");
+        } else {
+            self.wr.write_char('{');
+            self.indent += 2;
+            f();
+            self.wr.write_char('\n');
+            self.indent -= 2;
+            self.wr.write_str(spaces(self.indent));
+            self.wr.write_char('}');
+        }
+    }
+    fn emit_map_elt_key(&self, idx: uint, f: &fn()) {
+        if idx == 0 {
+            self.wr.write_char('\n');
+        } else {
+            self.wr.write_str(",\n");
+        }
+        self.wr.write_str(spaces(self.indent));
+        f();
+    }
+
+    fn emit_map_elt_val(&self, _idx: uint, f: &fn()) {
+        self.wr.write_str(": ");
+        f();
+    }
 }
 
-impl<S:serialize::Encoder> serialize::Encodable<S> for Json {
-    fn encode(&self, s: &S) {
+impl<E: serialize::Encoder> serialize::Encodable<E> for Json {
+    fn encode(&self, e: &E) {
         match *self {
-            Number(v) => v.encode(s),
-            String(ref v) => v.encode(s),
-            Boolean(v) => v.encode(s),
-            List(ref v) => v.encode(s),
-            Object(ref v) => {
-                do s.emit_rec || {
-                    let mut idx = 0;
-                    for v.each |&(key, value)| {
-                        do s.emit_field(*key, idx) {
-                            value.encode(s);
-                        }
-                        idx += 1;
-                    }
-                }
-            },
-            Null => s.emit_nil(),
+            Number(v) => v.encode(e),
+            String(ref v) => v.encode(e),
+            Boolean(v) => v.encode(e),
+            List(ref v) => v.encode(e),
+            Object(ref v) => v.encode(e),
+            Null => e.emit_nil(),
         }
     }
 }
@@ -752,37 +736,20 @@ pub fn from_str(s: &str) -> Result<Json, Error> {
     }
 }
 
-pub struct Decoder<'self> {
-    priv json: Json,
-    priv mut stack: ~[&'self Json],
+pub struct Decoder {
+    priv mut stack: ~[Json],
 }
 
 pub fn Decoder(json: Json) -> Decoder {
-    Decoder { json: json, stack: ~[] }
-}
-
-priv impl<'self> Decoder<'self> {
-    fn peek(&self) -> &'self Json {
-        if vec::uniq_len(&const self.stack) == 0 {
-            self.stack.push(&self.json);
-        }
-        self.stack[vec::uniq_len(&const self.stack) - 1]
-    }
-
-    fn pop(&self) -> &'self Json {
-        if vec::uniq_len(&const self.stack) == 0 {
-            self.stack.push(&self.json);
-        }
-        self.stack.pop()
-    }
+    Decoder { stack: ~[json] }
 }
 
-impl<'self> serialize::Decoder for Decoder<'self> {
+impl serialize::Decoder for Decoder {
     fn read_nil(&self) -> () {
         debug!("read_nil");
-        match *self.pop() {
+        match self.stack.pop() {
             Null => (),
-            _ => fail!(~"not a null")
+            value => fail!(fmt!("not a null: %?", value))
         }
     }
 
@@ -800,9 +767,9 @@ impl<'self> serialize::Decoder for Decoder<'self> {
 
     fn read_bool(&self) -> bool {
         debug!("read_bool");
-        match *self.pop() {
+        match self.stack.pop() {
             Boolean(b) => b,
-            _ => fail!(~"not a boolean")
+            value => fail!(fmt!("not a boolean: %?", value))
         }
     }
 
@@ -810,45 +777,27 @@ impl<'self> serialize::Decoder for Decoder<'self> {
     fn read_f32(&self) -> f32 { self.read_float() as f32 }
     fn read_float(&self) -> float {
         debug!("read_float");
-        match *self.pop() {
+        match self.stack.pop() {
             Number(f) => f,
-            _ => fail!(~"not a number")
+            value => fail!(fmt!("not a number: %?", value))
         }
     }
 
     fn read_char(&self) -> char {
         let mut v = ~[];
-        for str::each_char(self.read_owned_str()) |c| { v.push(c) }
+        for str::each_char(self.read_str()) |c| { v.push(c) }
         if v.len() != 1 { fail!(~"string must have one character") }
         v[0]
     }
 
-    fn read_owned_str(&self) -> ~str {
-        debug!("read_owned_str");
-        match *self.pop() {
-            String(ref s) => copy *s,
-            ref json => fail!(fmt!("not a string: %?", *json))
+    fn read_str(&self) -> ~str {
+        debug!("read_str");
+        match self.stack.pop() {
+            String(s) => s,
+            json => fail!(fmt!("not a string: %?", json))
         }
     }
 
-    fn read_managed_str(&self) -> @str {
-        debug!("read_managed_str");
-        match *self.pop() {
-            String(ref s) => s.to_managed(),
-            ref json => fail!(fmt!("not a string: %?", *json))
-        }
-    }
-
-    fn read_owned<T>(&self, f: &fn() -> T) -> T {
-        debug!("read_owned()");
-        f()
-    }
-
-    fn read_managed<T>(&self, f: &fn() -> T) -> T {
-        debug!("read_managed()");
-        f()
-    }
-
     fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T {
         debug!("read_enum(%s)", name);
         f()
@@ -856,12 +805,20 @@ impl<'self> serialize::Decoder for Decoder<'self> {
 
     fn read_enum_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T {
         debug!("read_enum_variant(names=%?)", names);
-        let name = match *self.peek() {
-            String(ref s) => s,
-            List([String(ref s), .. _]) => s,
+        let name = match self.stack.pop() {
+            String(s) => s,
+            List(list) => {
+                do vec::consume_reverse(list) |_i, v| {
+                    self.stack.push(v);
+                }
+                match self.stack.pop() {
+                    String(s) => s,
+                    value => fail!(fmt!("invalid variant name: %?", value)),
+                }
+            }
             ref json => fail!(fmt!("invalid variant: %?", *json)),
         };
-        let idx = match vec::position(names, |n| str::eq_slice(*n, *name)) {
+        let idx = match vec::position(names, |n| str::eq_slice(*n, name)) {
             Some(idx) => idx,
             None => fail!(fmt!("Unknown variant name: %?", name)),
         };
@@ -870,108 +827,87 @@ impl<'self> serialize::Decoder for Decoder<'self> {
 
     fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
         debug!("read_enum_variant_arg(idx=%u)", idx);
-        match *self.peek() {
-            List(ref list) => {
-                self.stack.push(&list[idx + 1]);
-                f()
-            }
-            ref json => fail!(fmt!("not a list: %?", json)),
-        }
-    }
-
-    fn read_owned_vec<T>(&self, f: &fn(uint) -> T) -> T {
-        debug!("read_owned_vec()");
-        let len = match *self.peek() {
-            List(ref list) => list.len(),
-            _ => fail!(~"not a list"),
-        };
-        let res = f(len);
-        self.pop();
-        res
-    }
-
-    fn read_managed_vec<T>(&self, f: &fn(uint) -> T) -> T {
-        debug!("read_owned_vec()");
-        let len = match *self.peek() {
-            List(ref list) => list.len(),
-            _ => fail!(~"not a list"),
-        };
-        let res = f(len);
-        self.pop();
-        res
+        f()
     }
 
-    fn read_vec_elt<T>(&self, idx: uint, f: &fn() -> T) -> T {
-        debug!("read_vec_elt(idx=%u)", idx);
-        match *self.peek() {
-            List(ref list) => {
-                self.stack.push(&list[idx]);
-                f()
+    fn read_seq<T>(&self, f: &fn(uint) -> T) -> T {
+        debug!("read_seq()");
+        let len = match self.stack.pop() {
+            List(list) => {
+                let len = list.len();
+                do vec::consume_reverse(list) |_i, v| {
+                    self.stack.push(v);
+                }
+                len
             }
             _ => fail!(~"not a list"),
-        }
+        };
+        f(len)
     }
 
-    fn read_rec<T>(&self, f: &fn() -> T) -> T {
-        debug!("read_rec()");
-        let value = f();
-        self.pop();
-        value
+    fn read_seq_elt<T>(&self, idx: uint, f: &fn() -> T) -> T {
+        debug!("read_seq_elt(idx=%u)", idx);
+        f()
     }
 
-    fn read_struct<T>(&self, _name: &str, _len: uint, f: &fn() -> T) -> T {
-        debug!("read_struct()");
+    fn read_struct<T>(&self, name: &str, len: uint, f: &fn() -> T) -> T {
+        debug!("read_struct(name=%s, len=%u)", name, len);
         let value = f();
-        self.pop();
+        self.stack.pop();
         value
     }
 
     fn read_field<T>(&self, name: &str, idx: uint, f: &fn() -> T) -> T {
-        debug!("read_rec_field(%s, idx=%u)", name, idx);
-        let top = self.peek();
-        match *top {
-            Object(ref obj) => {
-                match obj.find(&name.to_owned()) {
+        debug!("read_field(%s, idx=%u)", name, idx);
+        match self.stack.pop() {
+            Object(obj) => {
+                let mut obj = obj;
+                let value = match obj.pop(&name.to_owned()) {
                     None => fail!(fmt!("no such field: %s", name)),
                     Some(json) => {
                         self.stack.push(json);
                         f()
                     }
-                }
+                };
+                self.stack.push(Object(obj));
+                value
             }
-            Number(_) => fail!(~"num"),
-            String(_) => fail!(~"str"),
-            Boolean(_) => fail!(~"bool"),
-            List(_) => fail!(fmt!("list: %?", top)),
-            Null => fail!(~"null"),
-
-            //_ => fail!(fmt!("not an object: %?", *top))
+            value => fail!(fmt!("not an object: %?", value))
         }
     }
 
-    fn read_tup<T>(&self, len: uint, f: &fn() -> T) -> T {
-        debug!("read_tup(len=%u)", len);
-        let value = f();
-        self.pop();
-        value
+    fn read_option<T>(&self, f: &fn(bool) -> T) -> T {
+        match self.stack.pop() {
+            Null => f(false),
+            value => { self.stack.push(value); f(true) }
+        }
     }
 
-    fn read_tup_elt<T>(&self, idx: uint, f: &fn() -> T) -> T {
-        debug!("read_tup_elt(idx=%u)", idx);
-        match *self.peek() {
-            List(ref list) => {
-                self.stack.push(&list[idx]);
-                f()
+    fn read_map<T>(&self, f: &fn(uint) -> T) -> T {
+        debug!("read_map()");
+        let len = match self.stack.pop() {
+            Object(obj) => {
+                let mut obj = obj;
+                let len = obj.len();
+                do obj.consume |key, value| {
+                    self.stack.push(value);
+                    self.stack.push(String(key));
+                }
+                len
             }
-            _ => fail!(~"not a list")
-        }
+            json => fail!(fmt!("not an object: %?", json)),
+        };
+        f(len)
     }
 
-    fn read_option<T>(&self, f: &fn(bool) -> T) -> T {
-        match *self.peek() {
-            Null => { self.pop(); f(false) }
-            _ => f(true),
-        }
+    fn read_map_elt_key<T>(&self, idx: uint, f: &fn() -> T) -> T {
+        debug!("read_map_elt_key(idx=%u)", idx);
+        f()
+    }
+
+    fn read_map_elt_val<T>(&self, idx: uint, f: &fn() -> T) -> T {
+        debug!("read_map_elt_val(idx=%u)", idx);
+        f()
     }
 }
 
@@ -1229,6 +1165,30 @@ mod tests {
 
     use std::serialize::Decodable;
 
+    #[auto_encode]
+    #[auto_decode]
+    #[deriving(Eq)]
+    enum Animal {
+        Dog,
+        Frog(~str, int)
+    }
+
+    #[auto_encode]
+    #[auto_decode]
+    #[deriving(Eq)]
+    struct Inner {
+        a: (),
+        b: uint,
+        c: ~[~str],
+    }
+
+    #[auto_encode]
+    #[auto_decode]
+    #[deriving(Eq)]
+    struct Outer {
+        inner: ~[Inner],
+    }
+
     fn mk_object(items: &[(~str, Json)]) -> Json {
         let mut d = ~LinearMap::new();
 
@@ -1244,42 +1204,49 @@ mod tests {
     #[test]
     fn test_write_null() {
         assert_eq!(to_str(&Null), ~"null");
+        assert_eq!(to_pretty_str(&Null), ~"null");
     }
 
+
     #[test]
     fn test_write_number() {
         assert_eq!(to_str(&Number(3f)), ~"3");
+        assert_eq!(to_pretty_str(&Number(3f)), ~"3");
+
         assert_eq!(to_str(&Number(3.1f)), ~"3.1");
+        assert_eq!(to_pretty_str(&Number(3.1f)), ~"3.1");
+
         assert_eq!(to_str(&Number(-1.5f)), ~"-1.5");
+        assert_eq!(to_pretty_str(&Number(-1.5f)), ~"-1.5");
+
         assert_eq!(to_str(&Number(0.5f)), ~"0.5");
+        assert_eq!(to_pretty_str(&Number(0.5f)), ~"0.5");
     }
 
     #[test]
     fn test_write_str() {
         assert_eq!(to_str(&String(~"")), ~"\"\"");
+        assert_eq!(to_pretty_str(&String(~"")), ~"\"\"");
+
         assert_eq!(to_str(&String(~"foo")), ~"\"foo\"");
+        assert_eq!(to_pretty_str(&String(~"foo")), ~"\"foo\"");
     }
 
     #[test]
     fn test_write_bool() {
         assert_eq!(to_str(&Boolean(true)), ~"true");
+        assert_eq!(to_pretty_str(&Boolean(true)), ~"true");
+
         assert_eq!(to_str(&Boolean(false)), ~"false");
+        assert_eq!(to_pretty_str(&Boolean(false)), ~"false");
     }
 
     #[test]
     fn test_write_list() {
         assert_eq!(to_str(&List(~[])), ~"[]");
-        assert_eq!(to_str(&List(~[Boolean(true)])), ~"[true]");
-        assert_eq!(to_str(&List(~[
-            Boolean(false),
-            Null,
-            List(~[String(~"foo\nbar"), Number(3.5f)])
-        ])), ~"[false,null,[\"foo\\nbar\",3.5]]");
-    }
-
-    #[test]
-    fn test_write_list_pretty() {
         assert_eq!(to_pretty_str(&List(~[])), ~"[]");
+
+        assert_eq!(to_str(&List(~[Boolean(true)])), ~"[true]");
         assert_eq!(
             to_pretty_str(&List(~[Boolean(true)])),
             ~"\
@@ -1287,6 +1254,12 @@ mod tests {
                 true\n\
             ]"
         );
+
+        assert_eq!(to_str(&List(~[
+            Boolean(false),
+            Null,
+            List(~[String(~"foo\nbar"), Number(3.5f)])
+        ])), ~"[false,null,[\"foo\\nbar\",3.5]]");
         assert_eq!(
             to_pretty_str(&List(~[
                 Boolean(false),
@@ -1308,11 +1281,21 @@ mod tests {
     #[test]
     fn test_write_object() {
         assert_eq!(to_str(&mk_object(~[])), ~"{}");
+        assert_eq!(to_pretty_str(&mk_object(~[])), ~"{}");
+
         assert_eq!(
             to_str(&mk_object(~[(~"a", Boolean(true))])),
             ~"{\"a\":true}"
         );
         assert_eq!(
+            to_pretty_str(&mk_object(~[(~"a", Boolean(true))])),
+            ~"\
+            {\n  \
+                \"a\": true\n\
+            }"
+        );
+
+        assert_eq!(
             to_str(&mk_object(~[
                 (~"b", List(~[
                     mk_object(~[(~"c", String(~"\x0c\r"))]),
@@ -1326,29 +1309,6 @@ mod tests {
                 ]\
             }"
         );
-        let a = mk_object(~[
-            (~"a", Boolean(true)),
-            (~"b", List(~[
-                mk_object(~[(~"c", String(~"\x0c\r"))]),
-                mk_object(~[(~"d", String(~""))])
-            ]))
-        ]);
-        // We can't compare the strings directly because the object fields be
-        // printed in a different order.
-        let b = from_str(to_str(&a)).unwrap();
-        assert_eq!(a, b);
-    }
-
-    #[test]
-    fn test_write_object_pretty() {
-        assert_eq!(to_pretty_str(&mk_object(~[])), ~"{\n}");
-        assert_eq!(
-            to_pretty_str(&mk_object(~[(~"a", Boolean(true))])),
-            ~"\
-            {\n  \
-                \"a\": true\n\
-            }"
-        );
         assert_eq!(
             to_pretty_str(&mk_object(~[
                 (~"b", List(~[
@@ -1368,6 +1328,7 @@ mod tests {
                 ]\n\
             }"
         );
+
         let a = mk_object(~[
             (~"a", Boolean(true)),
             (~"b", List(~[
@@ -1375,63 +1336,44 @@ mod tests {
                 mk_object(~[(~"d", String(~""))])
             ]))
         ]);
+
         // We can't compare the strings directly because the object fields be
         // printed in a different order.
-        let b = from_str(to_str(&a)).unwrap();
-        assert_eq!(a, b);
-    }
-
-    #[auto_encode]
-    #[auto_decode]
-    #[deriving(Eq)]
-    enum Animal {
-        Dog,
-        Frog(~str, int)
+        assert_eq!(copy a, from_str(to_str(&a)).unwrap());
+        assert_eq!(copy a, from_str(to_pretty_str(&a)).unwrap());
     }
 
     #[test]
-    fn test_write_enum_no_args() {
+    fn test_write_enum() {
         let animal = Dog;
+        assert_eq!(
+            do io::with_str_writer |wr| {
+                let encoder = Encoder(wr);
+                animal.encode(&encoder);
+            },
+            ~"\"Dog\""
+        );
+        assert_eq!(
+            do io::with_str_writer |wr| {
+                let encoder = PrettyEncoder(wr);
+                animal.encode(&encoder);
+            },
+            ~"\"Dog\""
+        );
 
-        let s = do io::with_str_writer |wr| {
-            let encoder = Encoder(wr);
-            animal.encode(&encoder);
-        };
-        assert_eq!(s, ~"\"Dog\"");
-    }
-
-    #[test]
-    fn test_write_enum_no_args_pretty() {
-        let animal = Dog;
-
-        let s = do io::with_str_writer |wr| {
-            let encoder = PrettyEncoder(wr);
-            animal.encode(&encoder);
-        };
-        assert_eq!(s, ~"\"Dog\"");
-    }
-
-    #[test]
-    fn test_write_enum_multiple_args() {
-        let animal = Frog(~"Henry", 349);
-
-        let s = do io::with_str_writer |wr| {
-            let encoder = Encoder(wr);
-            animal.encode(&encoder);
-        };
-        assert_eq!(s, ~"[\"Frog\",\"Henry\",349]");
-    }
-
-    #[test]
-    fn test_write_enum_multiple_args_pretty() {
         let animal = Frog(~"Henry", 349);
-
-        let s = do io::with_str_writer |wr| {
-            let encoder = PrettyEncoder(wr);
-            animal.encode(&encoder);
-        };
         assert_eq!(
-            s,
+            do io::with_str_writer |wr| {
+                let encoder = Encoder(wr);
+                animal.encode(&encoder);
+            },
+            ~"[\"Frog\",\"Henry\",349]"
+        );
+        assert_eq!(
+            do io::with_str_writer |wr| {
+                let encoder = PrettyEncoder(wr);
+                animal.encode(&encoder);
+            },
             ~"\
             [\n  \
                 \"Frog\",\n  \
@@ -1449,10 +1391,7 @@ mod tests {
             value.encode(&encoder);
         };
         assert_eq!(s, ~"\"jodhpurs\"");
-    }
 
-    #[test]
-    fn test_write_some_pretty() {
         let value = Some(~"jodhpurs");
         let s = do io::with_str_writer |wr| {
             let encoder = PrettyEncoder(wr);
@@ -1469,11 +1408,7 @@ mod tests {
             value.encode(&encoder);
         };
         assert_eq!(s, ~"null");
-    }
 
-    #[test]
-    fn test_write_none_pretty() {
-        let value: Option<~str> = None;
         let s = do io::with_str_writer |wr| {
             let encoder = Encoder(wr);
             value.encode(&encoder);
@@ -1523,6 +1458,18 @@ mod tests {
     }
 
     #[test]
+    fn test_decode_identifiers() {
+        let v: () = Decodable::decode(&Decoder(from_str(~"null").unwrap()));
+        assert_eq!(v, ());
+
+        let v: bool = Decodable::decode(&Decoder(from_str(~"true").unwrap()));
+        assert_eq!(v, true);
+
+        let v: bool = Decodable::decode(&Decoder(from_str(~"false").unwrap()));
+        assert_eq!(v, false);
+    }
+
+    #[test]
     fn test_read_number() {
         assert_eq!(from_str(~"+"),
             Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"}));
@@ -1551,6 +1498,30 @@ mod tests {
     }
 
     #[test]
+    fn test_decode_numbers() {
+        let v: float = Decodable::decode(&Decoder(from_str(~"3").unwrap()));
+        assert_eq!(v, 3f);
+
+        let v: float = Decodable::decode(&Decoder(from_str(~"3.1").unwrap()));
+        assert_eq!(v, 3.1f);
+
+        let v: float = Decodable::decode(&Decoder(from_str(~"-1.2").unwrap()));
+        assert_eq!(v, -1.2f);
+
+        let v: float = Decodable::decode(&Decoder(from_str(~"0.4").unwrap()));
+        assert_eq!(v, 0.4f);
+
+        let v: float = Decodable::decode(&Decoder(from_str(~"0.4e5").unwrap()));
+        assert_eq!(v, 0.4e5f);
+
+        let v: float = Decodable::decode(&Decoder(from_str(~"0.4e15").unwrap()));
+        assert_eq!(v, 0.4e15f);
+
+        let v: float = Decodable::decode(&Decoder(from_str(~"0.4e-01").unwrap()));
+        assert_eq!(v, 0.4e-01f);
+    }
+
+    #[test]
     fn test_read_str() {
         assert_eq!(from_str(~"\""),
             Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing string"
@@ -1567,12 +1538,38 @@ mod tests {
         assert_eq!(from_str(~"\"\\r\""), Ok(String(~"\r")));
         assert_eq!(from_str(~"\"\\t\""), Ok(String(~"\t")));
         assert_eq!(from_str(~" \"foo\" "), Ok(String(~"foo")));
+        assert_eq!(from_str(~"\"\\u12ab\""), Ok(String(~"\u12ab")));
+        assert_eq!(from_str(~"\"\\uAB12\""), Ok(String(~"\uAB12")));
     }
 
     #[test]
-    fn test_unicode_hex_escapes_in_str() {
-        assert_eq!(from_str(~"\"\\u12ab\""), Ok(String(~"\u12ab")));
-        assert_eq!(from_str(~"\"\\uAB12\""), Ok(String(~"\uAB12")));
+    fn test_decode_str() {
+        let v: ~str = Decodable::decode(&Decoder(from_str(~"\"\"").unwrap()));
+        assert_eq!(v, ~"");
+
+        let v: ~str = Decodable::decode(&Decoder(from_str(~"\"foo\"").unwrap()));
+        assert_eq!(v, ~"foo");
+
+        let v: ~str = Decodable::decode(&Decoder(from_str(~"\"\\\"\"").unwrap()));
+        assert_eq!(v, ~"\"");
+
+        let v: ~str = Decodable::decode(&Decoder(from_str(~"\"\\b\"").unwrap()));
+        assert_eq!(v, ~"\x08");
+
+        let v: ~str = Decodable::decode(&Decoder(from_str(~"\"\\n\"").unwrap()));
+        assert_eq!(v, ~"\n");
+
+        let v: ~str = Decodable::decode(&Decoder(from_str(~"\"\\r\"").unwrap()));
+        assert_eq!(v, ~"\r");
+
+        let v: ~str = Decodable::decode(&Decoder(from_str(~"\"\\t\"").unwrap()));
+        assert_eq!(v, ~"\t");
+
+        let v: ~str = Decodable::decode(&Decoder(from_str(~"\"\\u12ab\"").unwrap()));
+        assert_eq!(v, ~"\u12ab");
+
+        let v: ~str = Decodable::decode(&Decoder(from_str(~"\"\\uAB12\"").unwrap()));
+        assert_eq!(v, ~"\uAB12");
     }
 
     #[test]
@@ -1602,6 +1599,28 @@ mod tests {
     }
 
     #[test]
+    fn test_decode_list() {
+        let v: ~[()] = Decodable::decode(&Decoder(from_str(~"[]").unwrap()));
+        assert_eq!(v, ~[]);
+
+        let v: ~[()] = Decodable::decode(&Decoder(from_str(~"[null]").unwrap()));
+        assert_eq!(v, ~[()]);
+
+
+        let v: ~[bool] = Decodable::decode(&Decoder(from_str(~"[true]").unwrap()));
+        assert_eq!(v, ~[true]);
+
+        let v: ~[bool] = Decodable::decode(&Decoder(from_str(~"[true]").unwrap()));
+        assert_eq!(v, ~[true]);
+
+        let v: ~[int] = Decodable::decode(&Decoder(from_str(~"[3, 1]").unwrap()));
+        assert_eq!(v, ~[3, 1]);
+
+        let v: ~[~[uint]] = Decodable::decode(&Decoder(from_str(~"[[3], [1, 2]]").unwrap()));
+        assert_eq!(v, ~[~[3], ~[1, 2]]);
+    }
+
+    #[test]
     fn test_read_object() {
         assert_eq!(from_str(~"{"),
             Err(Error {
@@ -1693,34 +1712,56 @@ mod tests {
     }
 
     #[test]
-    fn test_read_none() {
+    fn test_decode_struct() {
+        let s = ~"{
+            \"inner\": [
+                { \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
+            ]
+        }";
+        let v: Outer = Decodable::decode(&Decoder(from_str(s).unwrap()));
+        assert_eq!(
+            v,
+            Outer {
+                inner: ~[
+                    Inner { a: (), b: 2, c: ~[~"abc", ~"xyz"] }
+                ]
+            }
+        );
+    }
+
+    #[test]
+    fn test_decode_option() {
         let decoder = Decoder(from_str(~"null").unwrap());
         let value: Option<~str> = Decodable::decode(&decoder);
         assert_eq!(value, None);
-    }
 
-    #[test]
-    fn test_read_some() {
         let decoder = Decoder(from_str(~"\"jodhpurs\"").unwrap());
         let value: Option<~str> = Decodable::decode(&decoder);
         assert_eq!(value, Some(~"jodhpurs"));
     }
 
     #[test]
-    fn test_read_enum_no_args() {
+    fn test_decode_enum() {
         let decoder = Decoder(from_str(~"\"Dog\"").unwrap());
         let value: Animal = Decodable::decode(&decoder);
         assert_eq!(value, Dog);
-    }
 
-    #[test]
-    fn test_read_enum_multiple_args() {
         let decoder = Decoder(from_str(~"[\"Frog\",\"Henry\",349]").unwrap());
         let value: Animal = Decodable::decode(&decoder);
         assert_eq!(value, Frog(~"Henry", 349));
     }
 
     #[test]
+    fn test_decode_map() {
+        let s = ~"{\"a\": \"Dog\", \"b\": [\"Frog\", \"Henry\", 349]}";
+        let decoder = Decoder(from_str(s).unwrap());
+        let mut map: LinearMap<~str, Animal> = Decodable::decode(&decoder);
+
+        assert_eq!(map.pop(&~"a"), Some(Dog));
+        assert_eq!(map.pop(&~"b"), Some(Frog(~"Henry", 349)));
+    }
+
+    #[test]
     fn test_multiline_errors() {
         assert_eq!(from_str(~"{\n  \"foo\":\n \"bar\""),
             Err(Error {