Leave unused keys in TOML while decoding

This commit is contained in:
Alex Crichton 2014-06-26 22:52:31 -07:00
parent 7ba80c5ac4
commit c28df7cb52

View file

@ -48,7 +48,7 @@ pub struct Encoder {
/// `Decodable` types to be generated by this decoder. The input is any /// `Decodable` types to be generated by this decoder. The input is any
/// arbitrary TOML value. /// arbitrary TOML value.
pub struct Decoder { pub struct Decoder {
toml: Option<Value>, pub toml: Option<Value>,
cur_field: Option<String>, cur_field: Option<String>,
} }
@ -403,10 +403,12 @@ impl Decoder {
impl serialize::Decoder<DecodeError> for Decoder { impl serialize::Decoder<DecodeError> for Decoder {
fn read_nil(&mut self) -> Result<(), DecodeError> { fn read_nil(&mut self) -> Result<(), DecodeError> {
match self.toml { match self.toml {
Some(String(ref s)) if s.len() == 0 => Ok(()), Some(String(ref s)) if s.len() == 0 => {}
Some(String(..)) => Err(self.err(NilTooLong)), Some(String(..)) => return Err(self.err(NilTooLong)),
ref found => Err(self.mismatch("string", found)), ref found => return Err(self.mismatch("string", found)),
} }
self.toml.take();
Ok(())
} }
fn read_uint(&mut self) -> Result<uint, DecodeError> { fn read_uint(&mut self) -> Result<uint, DecodeError> {
self.read_i64().map(|i| i as uint) self.read_i64().map(|i| i as uint)
@ -428,7 +430,7 @@ impl serialize::Decoder<DecodeError> for Decoder {
} }
fn read_i64(&mut self) -> Result<i64, DecodeError> { fn read_i64(&mut self) -> Result<i64, DecodeError> {
match self.toml { match self.toml {
Some(Integer(i)) => Ok(i), Some(Integer(i)) => { self.toml.take(); Ok(i) }
ref found => Err(self.mismatch("integer", found)), ref found => Err(self.mismatch("integer", found)),
} }
} }
@ -443,7 +445,7 @@ impl serialize::Decoder<DecodeError> for Decoder {
} }
fn read_bool(&mut self) -> Result<bool, DecodeError> { fn read_bool(&mut self) -> Result<bool, DecodeError> {
match self.toml { match self.toml {
Some(Boolean(b)) => Ok(b), Some(Boolean(b)) => { self.toml.take(); Ok(b) }
ref found => Err(self.mismatch("bool", found)), ref found => Err(self.mismatch("bool", found)),
} }
} }
@ -457,16 +459,22 @@ impl serialize::Decoder<DecodeError> for Decoder {
self.read_f64().map(|f| f as f32) self.read_f64().map(|f| f as f32)
} }
fn read_char(&mut self) -> Result<char, DecodeError> { fn read_char(&mut self) -> Result<char, DecodeError> {
match self.toml { let ch = match self.toml {
Some(String(ref s)) if s.as_slice().char_len() == 1 => Some(String(ref s)) if s.as_slice().char_len() == 1 =>
Ok(s.as_slice().char_at(0)), s.as_slice().char_at(0),
ref found => Err(self.mismatch("string", found)), ref found => return Err(self.mismatch("string", found)),
} };
self.toml.take();
Ok(ch)
} }
fn read_str(&mut self) -> Result<String, DecodeError> { fn read_str(&mut self) -> Result<String, DecodeError> {
match self.toml.take() { match self.toml.take() {
Some(String(s)) => Ok(s), Some(String(s)) => Ok(s),
ref found => Err(self.mismatch("string", found)), found => {
let err = Err(self.mismatch("string", &found));
self.toml = found;
err
}
} }
} }
@ -535,11 +543,21 @@ impl serialize::Decoder<DecodeError> for Decoder {
_f_idx: uint, _f_idx: uint,
f: |&mut Decoder| -> Result<T, DecodeError>) f: |&mut Decoder| -> Result<T, DecodeError>)
-> Result<T, DecodeError> { -> Result<T, DecodeError> {
let field = f_name.to_string();
let toml = match self.toml { let toml = match self.toml {
Some(Table(ref mut table)) => table.pop(&f_name.to_string()), Some(Table(ref mut table)) => table.pop(&field),
ref found => return Err(self.mismatch("table", found)), ref found => return Err(self.mismatch("table", found)),
}; };
f(&mut self.sub_decoder(toml, f_name)) let mut d = self.sub_decoder(toml, f_name);
let ret = try!(f(&mut d));
match d.toml {
Some(value) => match self.toml {
Some(Table(ref mut table)) => { table.insert(field, value); }
_ => {}
},
None => {}
}
Ok(ret)
} }
fn read_tuple<T>(&mut self, fn read_tuple<T>(&mut self,
@ -957,4 +975,44 @@ mod tests {
); );
assert_eq!(v, decode!(Table(encode!(v)))); assert_eq!(v, decode!(Table(encode!(v))));
} }
#[test]
fn unused_fields() {
#[deriving(Encodable, Decodable, PartialEq, Show)]
struct Foo { a: int }
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() {
#[deriving(Encodable, Decodable, PartialEq, Show)]
struct Foo { a: Bar }
#[deriving(Encodable, Decodable, PartialEq, Show)]
struct Bar { a: int }
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)
})
})));
}
} }