From d1a83e6986470d2db81474bb7fd3eadada78b0a4 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 29 Mar 2013 09:04:35 -0700 Subject: std: add Encoder::emit_map and Decoder::read_map --- src/libstd/json.rs | 221 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 136 insertions(+), 85 deletions(-) (limited to 'src/libstd/json.rs') diff --git a/src/libstd/json.rs b/src/libstd/json.rs index ac7119d8ed8..f069547bc8c 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -156,6 +156,22 @@ impl serialize::Encoder for Encoder { 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 { @@ -276,6 +292,34 @@ impl serialize::Encoder for PrettyEncoder { 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 serialize::Encodable for Json { @@ -285,17 +329,7 @@ impl serialize::Encodable for Json { String(ref v) => v.encode(e), Boolean(v) => v.encode(e), List(ref v) => v.encode(e), - Object(ref v) => { - do e.emit_struct("Object", v.len())|| { - let mut idx = 0; - for v.each |&(key, value)| { - do e.emit_field(*key, idx) { - value.encode(e); - } - idx += 1; - } - } - }, + Object(ref v) => v.encode(e), Null => e.emit_nil(), } } @@ -702,37 +736,20 @@ pub fn from_str(s: &str) -> Result { } } -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)) } } @@ -750,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)) } } @@ -760,9 +777,9 @@ 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)) } } @@ -775,13 +792,12 @@ impl<'self> serialize::Decoder for Decoder<'self> { fn read_str(&self) -> ~str { debug!("read_str"); - match *self.pop() { - String(ref s) => copy *s, - ref json => fail!(fmt!("not a string: %?", *json)) + match self.stack.pop() { + String(s) => s, + json => fail!(fmt!("not a string: %?", json)) } } - fn read_enum(&self, name: &str, f: &fn() -> T) -> T { debug!("read_enum(%s)", name); f() @@ -790,9 +806,9 @@ impl<'self> serialize::Decoder for Decoder<'self> { #[cfg(stage0)] fn read_enum_variant(&self, f: &fn(uint) -> T) -> T { debug!("read_enum_variant()"); - let idx = match *self.peek() { - Null => 0, - _ => 1, + let idx = match self.stack.pop() { + Null => { self.stack.push(Null); 0 }, + value => { self.stack.push(value); 1 }, }; f(idx) } @@ -802,12 +818,20 @@ impl<'self> serialize::Decoder for Decoder<'self> { #[cfg(stage3)] fn read_enum_variant(&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)), }; @@ -816,73 +840,90 @@ impl<'self> serialize::Decoder for Decoder<'self> { fn read_enum_variant_arg(&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)), - } + f() } fn read_seq(&self, f: &fn(uint) -> T) -> T { debug!("read_seq()"); - let len = match *self.peek() { - List(ref list) => list.len(), + 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"), }; let res = f(len); - self.pop(); + self.stack.pop(); res } fn read_seq_elt(&self, idx: uint, f: &fn() -> T) -> T { debug!("read_seq_elt(idx=%u)", idx); - match *self.peek() { - List(ref list) => { - self.stack.push(&list[idx]); - f() - } - _ => fail!(~"not a list"), - } + f() } - fn read_struct(&self, _name: &str, _len: uint, f: &fn() -> T) -> T { - debug!("read_struct()"); + fn read_struct(&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(&self, name: &str, idx: uint, f: &fn() -> T) -> T { debug!("read_field(%s, idx=%u)", name, idx); - let top = self.peek(); - match *top { - Object(ref obj) => { - match obj.find(&name.to_owned()) { + 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_option(&self, f: &fn(bool) -> T) -> T { - match *self.peek() { - Null => { self.pop(); f(false) } - _ => f(true), + match self.stack.pop() { + Null => f(false), + value => { self.stack.push(value); f(true) } } } + + fn read_map(&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 + } + json => fail!(fmt!("not an object: %?", json)), + }; + f(len) + } + + fn read_map_elt_key(&self, idx: uint, f: &fn() -> T) -> T { + debug!("read_map_elt_key(idx=%u)", idx); + f() + } + + fn read_map_elt_val(&self, idx: uint, f: &fn() -> T) -> T { + debug!("read_map_elt_val(idx=%u)", idx); + f() + } } impl Eq for Json { @@ -1251,7 +1292,7 @@ mod tests { #[test] fn test_write_object_pretty() { - assert_eq!(to_pretty_str(&mk_object(~[])), ~"{\n}"); + assert_eq!(to_pretty_str(&mk_object(~[])), ~"{}"); assert_eq!( to_pretty_str(&mk_object(~[(~"a", Boolean(true))])), ~"\ @@ -1630,6 +1671,16 @@ mod tests { assert_eq!(value, Frog(~"Henry", 349)); } + #[test] + fn test_read_map() { + let s = ~"{\"a\": \"Dog\", \"b\": [\"Frog\", \"Henry\", 349]}"; + let decoder = Decoder(from_str(s).unwrap()); + let map: LinearMap<~str, Animal> = Decodable::decode(&decoder); + + assert_eq!(map.find(&~"a"), Some(Dog)); + assert_eq!(map.find(&~"b"), Some(Frog(~"Henry", 349))); + } + #[test] fn test_multiline_errors() { assert_eq!(from_str(~"{\n \"foo\":\n \"bar\""), -- cgit 1.4.1-3-g733a5