use std::mem; use rustc_serialize; use Value; use super::{Encoder, Error, State}; use super::Error::*; impl Encoder { fn table(&mut self, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { match mem::replace(&mut self.state, State::Start) { State::NextKey(key) => { let mut nested = Encoder::new(); try!(f(&mut nested)); self.toml.insert(key, Value::Table(nested.toml)); Ok(()) } State::NextArray(mut arr) => { let mut nested = Encoder::new(); try!(f(&mut nested)); arr.push(Value::Table(nested.toml)); self.state = State::NextArray(arr); Ok(()) } State::Start => f(self), State::NextMapKey => Err(Error::InvalidMapKeyLocation), } } fn seq(&mut self, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { let old = try!(self.seq_begin()); try!(f(self)); self.seq_end(old) } } impl rustc_serialize::Encoder for Encoder { type Error = Error; fn emit_nil(&mut self) -> Result<(), Error> { Ok(()) } fn emit_usize(&mut self, v: usize) -> Result<(), Error> { self.emit_i64(v as i64) } fn emit_u8(&mut self, v: u8) -> Result<(), Error> { self.emit_i64(v as i64) } fn emit_u16(&mut self, v: u16) -> Result<(), Error> { self.emit_i64(v as i64) } fn emit_u32(&mut self, v: u32) -> Result<(), Error> { self.emit_i64(v as i64) } fn emit_u64(&mut self, v: u64) -> Result<(), Error> { self.emit_i64(v as i64) } fn emit_isize(&mut self, v: isize) -> Result<(), Error> { self.emit_i64(v as i64) } fn emit_i8(&mut self, v: i8) -> Result<(), Error> { self.emit_i64(v as i64) } fn emit_i16(&mut self, v: i16) -> Result<(), Error> { self.emit_i64(v as i64) } fn emit_i32(&mut self, v: i32) -> Result<(), Error> { self.emit_i64(v as i64) } fn emit_i64(&mut self, v: i64) -> Result<(), Error> { self.emit_value(Value::Integer(v)) } fn emit_bool(&mut self, v: bool) -> Result<(), Error> { self.emit_value(Value::Boolean(v)) } fn emit_f32(&mut self, v: f32) -> Result<(), Error> { self.emit_f64(v as f64) } fn emit_f64(&mut self, v: f64) -> Result<(), Error> { self.emit_value(Value::Float(v)) } fn emit_char(&mut self, v: char) -> Result<(), Error> { self.emit_str(&v.to_string()) } fn emit_str(&mut self, v: &str) -> Result<(), Error> { self.emit_value(Value::String(v.to_string())) } fn emit_enum(&mut self, _name: &str, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { f(self) } fn emit_enum_variant(&mut self, _v_name: &str, _v_id: usize, _len: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { f(self) } fn emit_enum_variant_arg(&mut self, _a_idx: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { f(self) } fn emit_enum_struct_variant(&mut self, _v_name: &str, _v_id: usize, _len: usize, _f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { panic!() } fn emit_enum_struct_variant_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { panic!() } fn emit_struct(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { self.table(f) } fn emit_struct_field(&mut self, f_name: &str, _f_idx: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { let old = mem::replace(&mut self.state, State::NextKey(f_name.to_string())); try!(f(self)); if self.state != State::Start { return Err(NoValue) } self.state = old; Ok(()) } fn emit_tuple(&mut self, len: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { self.emit_seq(len, f) } fn emit_tuple_arg(&mut self, idx: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { self.emit_seq_elt(idx, f) } fn emit_tuple_struct(&mut self, _name: &str, _len: usize, _f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { unimplemented!() } fn emit_tuple_struct_arg(&mut self, _f_idx: usize, _f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { unimplemented!() } fn emit_option(&mut self, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { f(self) } fn emit_option_none(&mut self) -> Result<(), Error> { self.emit_none() } fn emit_option_some(&mut self, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { f(self) } fn emit_seq(&mut self, _len: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { self.seq(f) } fn emit_seq_elt(&mut self, _idx: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { f(self) } fn emit_map(&mut self, len: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { self.emit_struct("foo", len, f) } fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { self.table_key(f) } fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> Result<(), Error> where F: FnOnce(&mut Encoder) -> Result<(), Error> { f(self) } } impl rustc_serialize::Encodable for Value { fn encode(&self, e: &mut E) -> Result<(), E::Error> where E: rustc_serialize::Encoder { match *self { Value::String(ref s) => e.emit_str(s), Value::Integer(i) => e.emit_i64(i), Value::Float(f) => e.emit_f64(f), Value::Boolean(b) => e.emit_bool(b), Value::Datetime(ref s) => e.emit_str(s), Value::Array(ref a) => { e.emit_seq(a.len(), |e| { for item in a { try!(item.encode(e)); } Ok(()) }) } Value::Table(ref t) => { e.emit_map(t.len(), |e| { for (i, (key, value)) in t.iter().enumerate() { try!(e.emit_map_elt_key(i, |e| e.emit_str(key))); try!(e.emit_map_elt_val(i, |e| value.encode(e))); } Ok(()) }) } } } } #[cfg(test)] mod tests { use std::collections::{BTreeMap, HashSet}; use rustc_serialize::{self, Encodable, Decodable}; use {Encoder, Decoder, DecodeError}; use Value; use Value::{Table, Integer, Array, Float}; macro_rules! encode( ($t:expr) => ({ let mut e = Encoder::new(); $t.encode(&mut e).unwrap(); e.toml }) ); macro_rules! decode( ($t:expr) => ({ let mut d = Decoder::new($t); Decodable::decode(&mut d).unwrap() }) ); macro_rules! map( ($($k:ident, $v:expr),*) => ({ let mut _m = BTreeMap::new(); $(_m.insert(stringify!($k).to_string(), $v);)* _m }) ); #[test] fn smoke() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: isize } let v = Foo { a: 2 }; assert_eq!(encode!(v), map! { a, Integer(2) }); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn smoke_hyphen() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a_b: isize } let v = Foo { a_b: 2 }; assert_eq!(encode!(v), map! { a_b, Integer(2) }); assert_eq!(v, decode!(Table(encode!(v)))); let mut m = BTreeMap::new(); m.insert("a-b".to_string(), Integer(2)); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn nested() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: isize, b: Bar } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Bar { a: String } let v = Foo { a: 2, b: Bar { a: "test".to_string() } }; assert_eq!(encode!(v), map! { a, Integer(2), b, Table(map! { a, Value::String("test".to_string()) }) }); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn application_decode_error() { #[derive(PartialEq, Debug)] struct Range10(usize); impl Decodable for Range10 { fn decode(d: &mut D) -> Result { let x: usize = try!(Decodable::decode(d)); if x > 10 { Err(d.error("Value out of range!")) } else { Ok(Range10(x)) } } } let mut d_good = Decoder::new(Integer(5)); let mut d_bad1 = Decoder::new(Value::String("not an isize".to_string())); let mut d_bad2 = Decoder::new(Integer(11)); assert_eq!(Ok(Range10(5)), Decodable::decode(&mut d_good)); let err1: Result = Decodable::decode(&mut d_bad1); assert!(err1.is_err()); let err2: Result = Decodable::decode(&mut d_bad2); assert!(err2.is_err()); } #[test] fn array() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Vec } let v = Foo { a: vec![1, 2, 3, 4] }; assert_eq!(encode!(v), map! { a, Array(vec![ Integer(1), Integer(2), Integer(3), Integer(4) ]) }); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn tuple() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: (isize, isize, isize, isize) } let v = Foo { a: (1, 2, 3, 4) }; assert_eq!(encode!(v), map! { a, Array(vec![ Integer(1), Integer(2), Integer(3), Integer(4) ]) }); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn inner_structs_with_options() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Option>, b: Bar, } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Bar { a: String, b: f64, } let v = Foo { a: Some(Box::new(Foo { a: None, b: Bar { a: "foo".to_string(), b: 4.5 }, })), b: Bar { a: "bar".to_string(), b: 1.0 }, }; assert_eq!(encode!(v), map! { a, Table(map! { b, Table(map! { a, Value::String("foo".to_string()), b, Float(4.5) }) }), b, Table(map! { a, Value::String("bar".to_string()), b, Float(1.0) }) }); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn hashmap() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { map: BTreeMap, set: HashSet, } let v = Foo { map: { let mut m = BTreeMap::new(); m.insert("foo".to_string(), 10); m.insert("bar".to_string(), 4); m }, set: { let mut s = HashSet::new(); s.insert('a'); s }, }; assert_eq!(encode!(v), map! { map, Table(map! { foo, Integer(10), bar, Integer(4) }), set, Array(vec![Value::String("a".to_string())]) } ); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn tuple_struct() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo(isize, String, f64); let v = Foo(1, "foo".to_string(), 4.5); assert_eq!( encode!(v), map! { _field0, Integer(1), _field1, Value::String("foo".to_string()), _field2, Float(4.5) } ); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn table_array() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Vec, } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Bar { a: isize } let v = Foo { a: vec![Bar { a: 1 }, Bar { a: 2 }] }; assert_eq!( encode!(v), map! { a, Array(vec![ Table(map!{ a, Integer(1) }), Table(map!{ a, Integer(2) }), ]) } ); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn type_errors() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { bar: isize } let mut d = Decoder::new(Table(map! { bar, Float(1.0) })); let a: Result = Decodable::decode(&mut d); match a { Ok(..) => panic!("should not have decoded"), Err(e) => { assert_eq!(e.to_string(), "expected a value of type `integer`, but \ found a value of type `float` for the key `bar`"); } } } #[test] fn missing_errors() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { bar: isize } let mut d = Decoder::new(Table(map! { })); let a: Result = Decodable::decode(&mut d); match a { Ok(..) => panic!("should not have decoded"), Err(e) => { assert_eq!(e.to_string(), "expected a value of type `integer` for the key `bar`"); } } } #[test] fn parse_enum() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: E } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] enum E { Bar(isize), Baz(f64), Last(Foo2), } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo2 { test: String, } let v = Foo { a: E::Bar(10) }; assert_eq!( encode!(v), map! { a, Integer(10) } ); assert_eq!(v, decode!(Table(encode!(v)))); let v = Foo { a: E::Baz(10.2) }; assert_eq!( encode!(v), map! { a, Float(10.2) } ); assert_eq!(v, decode!(Table(encode!(v)))); let v = Foo { a: E::Last(Foo2 { test: "test".to_string() }) }; assert_eq!( encode!(v), map! { a, Table(map! { test, Value::String("test".to_string()) }) } ); assert_eq!(v, decode!(Table(encode!(v)))); } #[test] fn unused_fields() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: isize } let v = Foo { a: 2 }; let mut d = Decoder::new(Table(map! { a, Integer(2), b, Integer(5) })); assert_eq!(v, Decodable::decode(&mut d).unwrap()); assert_eq!(d.toml, Some(Table(map! { b, Integer(5) }))); } #[test] fn unused_fields2() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Bar } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Bar { a: isize } let v = Foo { a: Bar { a: 2 } }; let mut d = Decoder::new(Table(map! { a, Table(map! { a, Integer(2), b, Integer(5) }) })); assert_eq!(v, Decodable::decode(&mut d).unwrap()); assert_eq!(d.toml, Some(Table(map! { a, Table(map! { b, Integer(5) }) }))); } #[test] fn unused_fields3() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Bar } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Bar { a: isize } let v = Foo { a: Bar { a: 2 } }; let mut d = Decoder::new(Table(map! { a, Table(map! { a, Integer(2) }) })); assert_eq!(v, Decodable::decode(&mut d).unwrap()); assert_eq!(d.toml, None); } #[test] fn unused_fields4() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: BTreeMap } let v = Foo { a: map! { a, "foo".to_string() } }; let mut d = Decoder::new(Table(map! { a, Table(map! { a, Value::String("foo".to_string()) }) })); assert_eq!(v, Decodable::decode(&mut d).unwrap()); assert_eq!(d.toml, None); } #[test] fn unused_fields5() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Vec } let v = Foo { a: vec!["a".to_string()] }; let mut d = Decoder::new(Table(map! { a, Array(vec![Value::String("a".to_string())]) })); assert_eq!(v, Decodable::decode(&mut d).unwrap()); assert_eq!(d.toml, None); } #[test] fn unused_fields6() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Option> } let v = Foo { a: Some(vec![]) }; let mut d = Decoder::new(Table(map! { a, Array(vec![]) })); assert_eq!(v, Decodable::decode(&mut d).unwrap()); assert_eq!(d.toml, None); } #[test] fn unused_fields7() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Vec } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Bar { a: isize } let v = Foo { a: vec![Bar { a: 1 }] }; let mut d = Decoder::new(Table(map! { a, Array(vec![Table(map! { a, Integer(1), b, Integer(2) })]) })); assert_eq!(v, Decodable::decode(&mut d).unwrap()); assert_eq!(d.toml, Some(Table(map! { a, Array(vec![Table(map! { b, Integer(2) })]) }))); } #[test] fn unused_fields8() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: BTreeMap } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Bar { a: isize } let v = Foo { a: map! { a, Bar { a: 2 } } }; let mut d = Decoder::new(Table(map! { a, Table(map! { a, Table(map! { a, Integer(2), b, Integer(2) }) }) })); assert_eq!(v, Decodable::decode(&mut d).unwrap()); assert_eq!(d.toml, Some(Table(map! { a, Table(map! { a, Table(map! { b, Integer(2) }) }) }))); } #[test] fn empty_arrays() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Vec } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Bar; let v = Foo { a: vec![] }; let mut d = Decoder::new(Table(map! {})); assert_eq!(v, Decodable::decode(&mut d).unwrap()); } #[test] fn empty_arrays2() { #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Foo { a: Option> } #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct Bar; let v = Foo { a: None }; let mut d = Decoder::new(Table(map! {})); assert_eq!(v, Decodable::decode(&mut d).unwrap()); let v = Foo { a: Some(vec![]) }; let mut d = Decoder::new(Table(map! { a, Array(vec![]) })); assert_eq!(v, Decodable::decode(&mut d).unwrap()); } #[test] fn round_trip() { let toml = r#" [test] foo = "bar" [[values]] foo = "baz" [[values]] foo = "qux" "#; let value: Value = toml.parse().unwrap(); let val2 = ::encode_str(&value).parse().unwrap(); assert_eq!(value, val2); } }