From c28df7cb52f537975866b43ca28ea5d1a38f7d17 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 26 Jun 2014 22:52:31 -0700 Subject: Leave unused keys in TOML while decoding --- src/serialization.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 13 deletions(-) diff --git a/src/serialization.rs b/src/serialization.rs index 7011eb6..e5bce42 100644 --- a/src/serialization.rs +++ b/src/serialization.rs @@ -48,7 +48,7 @@ pub struct Encoder { /// `Decodable` types to be generated by this decoder. The input is any /// arbitrary TOML value. pub struct Decoder { - toml: Option, + pub toml: Option, cur_field: Option, } @@ -403,10 +403,12 @@ impl Decoder { impl serialize::Decoder for Decoder { fn read_nil(&mut self) -> Result<(), DecodeError> { match self.toml { - Some(String(ref s)) if s.len() == 0 => Ok(()), - Some(String(..)) => Err(self.err(NilTooLong)), - ref found => Err(self.mismatch("string", found)), + Some(String(ref s)) if s.len() == 0 => {} + Some(String(..)) => return Err(self.err(NilTooLong)), + ref found => return Err(self.mismatch("string", found)), } + self.toml.take(); + Ok(()) } fn read_uint(&mut self) -> Result { self.read_i64().map(|i| i as uint) @@ -428,7 +430,7 @@ impl serialize::Decoder for Decoder { } fn read_i64(&mut self) -> Result { match self.toml { - Some(Integer(i)) => Ok(i), + Some(Integer(i)) => { self.toml.take(); Ok(i) } ref found => Err(self.mismatch("integer", found)), } } @@ -443,7 +445,7 @@ impl serialize::Decoder for Decoder { } fn read_bool(&mut self) -> Result { match self.toml { - Some(Boolean(b)) => Ok(b), + Some(Boolean(b)) => { self.toml.take(); Ok(b) } ref found => Err(self.mismatch("bool", found)), } } @@ -457,16 +459,22 @@ impl serialize::Decoder for Decoder { self.read_f64().map(|f| f as f32) } fn read_char(&mut self) -> Result { - match self.toml { + let ch = match self.toml { Some(String(ref s)) if s.as_slice().char_len() == 1 => - Ok(s.as_slice().char_at(0)), - ref found => Err(self.mismatch("string", found)), - } + s.as_slice().char_at(0), + ref found => return Err(self.mismatch("string", found)), + }; + self.toml.take(); + Ok(ch) } fn read_str(&mut self) -> Result { match self.toml.take() { 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 for Decoder { _f_idx: uint, f: |&mut Decoder| -> Result) -> Result { + let field = f_name.to_string(); 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)), }; - 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(&mut self, @@ -957,4 +975,44 @@ mod tests { ); 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) + }) + }))); + } } -- cgit v1.2.3