about summary refs log tree commit diff
diff options
context:
space:
mode:
authorErick Tryzelaar <erick.tryzelaar@gmail.com>2013-03-29 09:04:35 -0700
committerErick Tryzelaar <erick.tryzelaar@gmail.com>2013-03-29 09:04:35 -0700
commitd1a83e6986470d2db81474bb7fd3eadada78b0a4 (patch)
tree5dfc51c8a151176fe374735ba12fc06913a288a9
parented62f6dfe0c8f3b8b2769c65bb7b7bb8b3815b1a (diff)
downloadrust-d1a83e6986470d2db81474bb7fd3eadada78b0a4.tar.gz
rust-d1a83e6986470d2db81474bb7fd3eadada78b0a4.zip
std: add Encoder::emit_map and Decoder::read_map
-rw-r--r--src/libstd/ebml.rs27
-rw-r--r--src/libstd/flatpipes.rs4
-rw-r--r--src/libstd/json.rs221
-rw-r--r--src/libstd/serialize.rs63
-rw-r--r--src/libstd/workcache.rs41
-rw-r--r--src/libsyntax/ext/auto_encode.rs10
6 files changed, 263 insertions, 103 deletions
diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs
index 6b216504e54..f7fe2f54c57 100644
--- a/src/libstd/ebml.rs
+++ b/src/libstd/ebml.rs
@@ -402,6 +402,21 @@ pub mod reader {
                 }
             }
         }
+
+        fn read_map<T>(&self, _f: &fn(uint) -> T) -> T {
+            debug!("read_map()");
+            fail!(~"read_map is unimplemented");
+        }
+
+        fn read_map_elt_key<T>(&self, idx: uint, _f: &fn() -> T) -> T {
+            debug!("read_map_elt_key(idx=%u)", idx);
+            fail!(~"read_map_elt_val is unimplemented");
+        }
+
+        fn read_map_elt_val<T>(&self, idx: uint, _f: &fn() -> T) -> T {
+            debug!("read_map_elt_val(idx=%u)", idx);
+            fail!(~"read_map_elt_val is unimplemented");
+        }
     }
 }
 
@@ -654,6 +669,18 @@ pub mod writer {
         fn emit_option_some(&self, f: &fn()) {
             self.emit_enum_variant("Some", 1, 1, f)
         }
+
+        fn emit_map(&self, _len: uint, _f: &fn()) {
+            fail!(~"emit_map is unimplemented");
+        }
+
+        fn emit_map_elt_key(&self, _idx: uint, _f: &fn()) {
+            fail!(~"emit_map_elt_key is unimplemented");
+        }
+
+        fn emit_map_elt_val(&self, _idx: uint, _f: &fn()) {
+            fail!(~"emit_map_elt_val is unimplemented");
+        }
     }
 }
 
diff --git a/src/libstd/flatpipes.rs b/src/libstd/flatpipes.rs
index 1a3a28f7492..f042e2226cd 100644
--- a/src/libstd/flatpipes.rs
+++ b/src/libstd/flatpipes.rs
@@ -466,8 +466,8 @@ pub mod flatteners {
         fn from_writer(w: @Writer) -> Self;
     }
 
-    impl<'self> FromReader for json::Decoder<'self> {
-        fn from_reader(r: @Reader) -> json::Decoder<'self> {
+    impl FromReader for json::Decoder {
+        fn from_reader(r: @Reader) -> json::Decoder {
             match json::from_reader(r) {
                 Ok(json) => {
                     json::Decoder(json)
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<E: serialize::Encoder> serialize::Encodable<E> for Json {
@@ -285,17 +329,7 @@ impl<E: serialize::Encoder> serialize::Encodable<E> 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<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))
         }
     }
 
@@ -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<T>(&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<T>(&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<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)),
         };
@@ -816,73 +840,90 @@ 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)),
-        }
+        f()
     }
 
     fn read_seq<T>(&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<T>(&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<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_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<T>(&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<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
+            }
+            json => fail!(fmt!("not an object: %?", json)),
+        };
+        f(len)
+    }
+
+    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()
+    }
 }
 
 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))])),
             ~"\
@@ -1631,6 +1672,16 @@ mod tests {
     }
 
     #[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\""),
             Err(Error {
diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs
index 83201653474..dd487218fe5 100644
--- a/src/libstd/serialize.rs
+++ b/src/libstd/serialize.rs
@@ -16,9 +16,8 @@ Core encoding and decoding interfaces.
 
 #[forbid(non_camel_case_types)];
 
-use core::at_vec;
 use core::prelude::*;
-use core::vec;
+use core::hashmap::linear::LinearMap;
 
 pub trait Encoder {
     // Primitive types:
@@ -56,6 +55,10 @@ pub trait Encoder {
     fn emit_option(&self, f: &fn());
     fn emit_option_none(&self);
     fn emit_option_some(&self, f: &fn());
+
+    fn emit_map(&self, len: uint, f: &fn());
+    fn emit_map_elt_key(&self, idx: uint, f: &fn());
+    fn emit_map_elt_val(&self, idx: uint, f: &fn());
 }
 
 pub trait Decoder {
@@ -96,6 +99,10 @@ pub trait Decoder {
 
     // Specialized types:
     fn read_option<T>(&self, f: &fn(bool) -> T) -> T;
+
+    fn read_map<T>(&self, f: &fn(uint) -> T) -> T;
+    fn read_map_elt_key<T>(&self, idx: uint, f: &fn() -> T) -> T;
+    fn read_map_elt_val<T>(&self, idx: uint, f: &fn() -> T) -> T;
 }
 
 pub trait Encodable<S:Encoder> {
@@ -529,6 +536,58 @@ impl<
     }
 }
 
+impl<
+    E: Encoder,
+    K: Encodable<E> + Hash + IterBytes + Eq,
+    V: Encodable<E>
+> Encodable<E> for LinearMap<K, V> {
+    fn encode(&self, e: &E) {
+        do e.emit_map(self.len()) {
+            let mut i = 0;
+            for self.each |&(key, val)| {
+                e.emit_map_elt_key(i, || key.encode(e));
+                e.emit_map_elt_val(i, || val.encode(e));
+                i += 1;
+            }
+        }
+    }
+}
+
+impl<
+    D: Decoder,
+    K: Decodable<D> + Hash + IterBytes + Eq,
+    V: Decodable<D>
+> Decodable<D> for LinearMap<K, V> {
+    #[cfg(stage0)]
+    fn decode(d: &D) -> LinearMap<K, V> {
+        do d.read_map |len| {
+            let mut map = LinearMap::new();
+            map.reserve_at_least(len);
+            for uint::range(0, len) |i| {
+                let key = d.read_map_elt_key(i, || Decodable::decode(d));
+                let val = d.read_map_elt_val(i, || Decodable::decode(d));
+                map.insert(key, val);
+            }
+            map
+        }
+    }
+
+    #[cfg(stage1)]
+    #[cfg(stage2)]
+    #[cfg(stage3)]
+    fn decode(d: &D) -> LinearMap<K, V> {
+        do d.read_map |len| {
+            let mut map = LinearMap::with_capacity(len);
+            for uint::range(0, len) |i| {
+                let key = d.read_map_elt_key(i, || Decodable::decode(d));
+                let val = d.read_map_elt_val(i, || Decodable::decode(d));
+                map.insert(key, val);
+            }
+            map
+        }
+    }
+}
+
 // ___________________________________________________________________________
 // Helper routines
 //
diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs
index f477a8c9f91..90f10ea5054 100644
--- a/src/libstd/workcache.rs
+++ b/src/libstd/workcache.rs
@@ -137,7 +137,11 @@ pub impl WorkKey {
     }
 }
 
-type WorkMap = LinearMap<WorkKey, ~str>;
+struct WorkMap(LinearMap<WorkKey, ~str>);
+
+impl WorkMap {
+    fn new() -> WorkMap { WorkMap(LinearMap::new()) }
+}
 
 impl<S:Encoder> Encodable<S> for WorkMap {
     fn encode(&self, s: &S) {
@@ -153,7 +157,7 @@ impl<S:Encoder> Encodable<S> for WorkMap {
 impl<D:Decoder> Decodable<D> for WorkMap {
     fn decode(d: &D) -> WorkMap {
         let v : ~[(WorkKey,~str)] = Decodable::decode(d);
-        let mut w = LinearMap::new();
+        let mut w = WorkMap::new();
         for v.each |&(k, v)| {
             w.insert(copy k, copy v);
         }
@@ -235,7 +239,7 @@ fn json_encode<T:Encodable<json::Encoder>>(t: &T) -> ~str {
 }
 
 // FIXME(#5121)
-fn json_decode<T:Decodable<json::Decoder<'static>>>(s: &str) -> T {
+fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
     do io::with_str_reader(s) |rdr| {
         let j = result::unwrap(json::from_reader(rdr));
         Decodable::decode(&json::Decoder(j))
@@ -260,18 +264,25 @@ pub impl Context {
     fn new(db: @Mut<Database>,
                   lg: @Mut<Logger>,
                   cfg: @json::Object) -> Context {
-        Context{db: db, logger: lg, cfg: cfg, freshness: LinearMap::new()}
+        Context {
+            db: db,
+            logger: lg,
+            cfg: cfg,
+            freshness: LinearMap::new()
+        }
     }
 
     fn prep<T:Owned +
               Encodable<json::Encoder> +
-              Decodable<json::Decoder<'static>>>( // FIXME(#5121)
+              Decodable<json::Decoder>>( // FIXME(#5121)
                   @self,
                   fn_name:&str,
                   blk: &fn(@Mut<Prep>)->Work<T>) -> Work<T> {
-        let p = @Mut(Prep {ctxt: self,
-                           fn_name: fn_name.to_owned(),
-                           declared_inputs: LinearMap::new()});
+        let p = @Mut(Prep {
+            ctxt: self,
+            fn_name: fn_name.to_owned(),
+            declared_inputs: WorkMap::new()
+        });
         blk(p)
     }
 }
@@ -283,7 +294,7 @@ trait TPrep {
     fn all_fresh(&self, cat:&str, map:&WorkMap) -> bool;
     fn exec<T:Owned +
               Encodable<json::Encoder> +
-              Decodable<json::Decoder<'static>>>( // FIXME(#5121)
+              Decodable<json::Decoder>>( // FIXME(#5121)
         &self, blk: ~fn(&Exec) -> T) -> Work<T>;
 }
 
@@ -324,7 +335,7 @@ impl TPrep for @Mut<Prep> {
 
     fn exec<T:Owned +
               Encodable<json::Encoder> +
-              Decodable<json::Decoder<'static>>>( // FIXME(#5121)
+              Decodable<json::Decoder>>( // FIXME(#5121)
             &self, blk: ~fn(&Exec) -> T) -> Work<T> {
         let mut bo = Some(blk);
 
@@ -349,8 +360,10 @@ impl TPrep for @Mut<Prep> {
                     let blk = blk.unwrap();
                     let chan = Cell(chan);
                     do task::spawn || {
-                        let exe = Exec{discovered_inputs: LinearMap::new(),
-                                       discovered_outputs: LinearMap::new()};
+                        let exe = Exec {
+                            discovered_inputs: WorkMap::new(),
+                            discovered_outputs: WorkMap::new(),
+                        };
                         let chan = chan.take();
                         let v = blk(&exe);
                         send_one(chan, (exe, v));
@@ -365,7 +378,7 @@ impl TPrep for @Mut<Prep> {
 
 pub impl<T:Owned +
          Encodable<json::Encoder> +
-         Decodable<json::Decoder<'static>>> Work<T> { // FIXME(#5121)
+         Decodable<json::Decoder>> Work<T> { // FIXME(#5121)
     fn new(p: @Mut<Prep>, e: Either<T,PortOne<(Exec,T)>>) -> Work<T> {
         Work { prep: p, res: Some(e) }
     }
@@ -374,7 +387,7 @@ pub impl<T:Owned +
 // FIXME (#3724): movable self. This should be in impl Work.
 fn unwrap<T:Owned +
             Encodable<json::Encoder> +
-            Decodable<json::Decoder<'static>>>( // FIXME(#5121)
+            Decodable<json::Decoder>>( // FIXME(#5121)
         w: Work<T>) -> T {
     let mut ww = w;
     let mut s = None;
diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs
index 3aceef9c73a..de01d258449 100644
--- a/src/libsyntax/ext/auto_encode.rs
+++ b/src/libsyntax/ext/auto_encode.rs
@@ -1280,6 +1280,16 @@ mod test {
             self.add_to_log(CallToEmitOptionSome);
             f();
         }
+
+        fn read_map<T>(&self, f: &fn(uint) -> T) -> T {
+            self.add_unknown_to_log(); f(0);
+        }
+        fn read_map_elt_key<T>(&self, idx: uint, f: &fn() -> T) -> T {
+            self.add_unknown_to_log(); f();
+        }
+        fn read_map_elt_val<T>(&self, idx: uint, f: &fn() -> T) -> T {
+            self.add_unknown_to_log(); f();
+        }
     }