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(&self, _f: &fn(uint) -> T) -> T { + debug!("read_map()"); + fail!(~"read_map is unimplemented"); + } + + fn read_map_elt_key(&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(&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 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: ~[] } + Decoder { stack: ~[json] } } -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() - } -} - -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\""), 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(&self, f: &fn(bool) -> T) -> T; + + fn read_map(&self, f: &fn(uint) -> T) -> T; + fn read_map_elt_key(&self, idx: uint, f: &fn() -> T) -> T; + fn read_map_elt_val(&self, idx: uint, f: &fn() -> T) -> T; } pub trait Encodable { @@ -529,6 +536,58 @@ impl< } } +impl< + E: Encoder, + K: Encodable + Hash + IterBytes + Eq, + V: Encodable +> Encodable for LinearMap { + 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 + Hash + IterBytes + Eq, + V: Decodable +> Decodable for LinearMap { + #[cfg(stage0)] + fn decode(d: &D) -> LinearMap { + 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 { + 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; +struct WorkMap(LinearMap); + +impl WorkMap { + fn new() -> WorkMap { WorkMap(LinearMap::new()) } +} impl Encodable for WorkMap { fn encode(&self, s: &S) { @@ -153,7 +157,7 @@ impl Encodable for WorkMap { impl Decodable 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: &T) -> ~str { } // FIXME(#5121) -fn json_decode>>(s: &str) -> T { +fn json_decode>(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, lg: @Mut, 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 + - Decodable>>( // FIXME(#5121) + Decodable>( // FIXME(#5121) @self, fn_name:&str, blk: &fn(@Mut)->Work) -> Work { - 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 + - Decodable>>( // FIXME(#5121) + Decodable>( // FIXME(#5121) &self, blk: ~fn(&Exec) -> T) -> Work; } @@ -324,7 +335,7 @@ impl TPrep for @Mut { fn exec + - Decodable>>( // FIXME(#5121) + Decodable>( // FIXME(#5121) &self, blk: ~fn(&Exec) -> T) -> Work { let mut bo = Some(blk); @@ -349,8 +360,10 @@ impl TPrep for @Mut { 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 { pub impl + - Decodable>> Work { // FIXME(#5121) + Decodable> Work { // FIXME(#5121) fn new(p: @Mut, e: Either>) -> Work { Work { prep: p, res: Some(e) } } @@ -374,7 +387,7 @@ pub impl + - Decodable>>( // FIXME(#5121) + Decodable>( // FIXME(#5121) w: Work) -> 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(&self, f: &fn(uint) -> T) -> T { + self.add_unknown_to_log(); f(0); + } + fn read_map_elt_key(&self, idx: uint, f: &fn() -> T) -> T { + self.add_unknown_to_log(); f(); + } + fn read_map_elt_val(&self, idx: uint, f: &fn() -> T) -> T { + self.add_unknown_to_log(); f(); + } }