From 156ab1e05c2202a4d64a7cd2a8ecf427d73cf0f7 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Fri, 9 Aug 2013 20:05:24 -0400 Subject: [PATCH 1/3] extra::json: use a different encoding for enums. It now uses `{"type": VariantName, "fields": [...]}`, which, according to @Seldaek, since all enums will have the same "shape" rather than being a weird ad-hoc array, will optimize better in javascript JITs. It also looks prettier, and makes more sense. --- src/libextra/json.rs | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/libextra/json.rs b/src/libextra/json.rs index ec9cb902d3d29..f1947cf033c56 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -134,18 +134,22 @@ impl serialize::Encoder for Encoder { _id: uint, cnt: uint, f: &fn(&mut Encoder)) { - // enums are encoded as strings or vectors: + // enums are encoded as strings or objects // Bunny => "Bunny" - // Kangaroo(34,"William") => ["Kangaroo",[34,"William"]] + // Kangaroo(34,"William") => {"type": "Kangaroo", "fields": [34,"William"]} if cnt == 0 { self.wr.write_str(escape_str(name)); } else { - self.wr.write_char('['); + self.wr.write_char('{'); + self.wr.write_str("\"type\""); + self.wr.write_char(':'); self.wr.write_str(escape_str(name)); self.wr.write_char(','); + self.wr.write_str("\"fields\""); + self.wr.write_str(":["); f(self); - self.wr.write_char(']'); + self.wr.write_str("]}"); } } @@ -947,14 +951,21 @@ impl serialize::Decoder for Decoder { debug!("read_enum_variant(names=%?)", names); let name = match self.stack.pop() { String(s) => s, - List(list) => { - for v in list.consume_rev_iter() { - self.stack.push(v); - } - match self.stack.pop() { - String(s) => s, - value => fail!("invalid variant name: %?", value), + Object(o) => { + let n = match o.find(&~"type").unwrap() { + &String(ref s) => s.clone(), + _ => fail!("invalidly encoded json"), + }; + match o.find(&~"fields").unwrap() { + &List(ref l) => { + for field in l.iter() { + self.stack.push(field.clone()); + } + }, + _ => fail!("invalidly encoded json") } + self.stack.push(Object(o)); + n } ref json => fail!("invalid variant: %?", *json), }; @@ -1522,7 +1533,7 @@ mod tests { let mut encoder = Encoder(wr); animal.encode(&mut encoder); }, - ~"[\"Frog\",\"Henry\",349]" + ~"{\"type\":\"Frog\",\"fields\":[\"Henry\",349]}" ); assert_eq!( do io::with_str_writer |wr| { @@ -1926,14 +1937,14 @@ mod tests { assert_eq!(value, Dog); let mut decoder = - Decoder(from_str("[\"Frog\",\"Henry\",349]").unwrap()); + Decoder(from_str("{\"type\":\"Frog\",\"fields\":[\"Henry\",349]}").unwrap()); let value: Animal = Decodable::decode(&mut decoder); assert_eq!(value, Frog(~"Henry", 349)); } #[test] fn test_decode_map() { - let s = ~"{\"a\": \"Dog\", \"b\": [\"Frog\", \"Henry\", 349]}"; + let s = ~"{\"a\": \"Dog\", \"b\": {\"type\":\"Frog\",\"fields\":[\"Henry\", 349]}}"; let mut decoder = Decoder(from_str(s).unwrap()); let mut map: TreeMap<~str, Animal> = Decodable::decode(&mut decoder); From e7b2712cefd7503aacb749305f870ce407539e1b Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sat, 10 Aug 2013 07:50:32 -0400 Subject: [PATCH 2/3] Use 'variant' instead of 'type' and expect --- src/libextra/json.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libextra/json.rs b/src/libextra/json.rs index f1947cf033c56..4e1fd676214db 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -142,7 +142,7 @@ impl serialize::Encoder for Encoder { self.wr.write_str(escape_str(name)); } else { self.wr.write_char('{'); - self.wr.write_str("\"type\""); + self.wr.write_str("\"variant\""); self.wr.write_char(':'); self.wr.write_str(escape_str(name)); self.wr.write_char(','); @@ -952,11 +952,11 @@ impl serialize::Decoder for Decoder { let name = match self.stack.pop() { String(s) => s, Object(o) => { - let n = match o.find(&~"type").unwrap() { + let n = match o.find(&~"variant").expect("invalidly encoded json") { &String(ref s) => s.clone(), _ => fail!("invalidly encoded json"), }; - match o.find(&~"fields").unwrap() { + match o.find(&~"fields").expect("invalidly encoded json") { &List(ref l) => { for field in l.iter() { self.stack.push(field.clone()); From 0f0dc0a783abe5155fdb7e0342b2d22c68acc22f Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sat, 10 Aug 2013 07:54:53 -0400 Subject: [PATCH 3/3] More complete s/type/variant --- src/libextra/json.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libextra/json.rs b/src/libextra/json.rs index 4e1fd676214db..085e60496a81e 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -136,7 +136,7 @@ impl serialize::Encoder for Encoder { f: &fn(&mut Encoder)) { // enums are encoded as strings or objects // Bunny => "Bunny" - // Kangaroo(34,"William") => {"type": "Kangaroo", "fields": [34,"William"]} + // Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]} if cnt == 0 { self.wr.write_str(escape_str(name)); @@ -1533,7 +1533,7 @@ mod tests { let mut encoder = Encoder(wr); animal.encode(&mut encoder); }, - ~"{\"type\":\"Frog\",\"fields\":[\"Henry\",349]}" + ~"{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}" ); assert_eq!( do io::with_str_writer |wr| { @@ -1937,14 +1937,14 @@ mod tests { assert_eq!(value, Dog); let mut decoder = - Decoder(from_str("{\"type\":\"Frog\",\"fields\":[\"Henry\",349]}").unwrap()); + Decoder(from_str("{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}").unwrap()); let value: Animal = Decodable::decode(&mut decoder); assert_eq!(value, Frog(~"Henry", 349)); } #[test] fn test_decode_map() { - let s = ~"{\"a\": \"Dog\", \"b\": {\"type\":\"Frog\",\"fields\":[\"Henry\", 349]}}"; + let s = ~"{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\"fields\":[\"Henry\", 349]}}"; let mut decoder = Decoder(from_str(s).unwrap()); let mut map: TreeMap<~str, Animal> = Decodable::decode(&mut decoder);