diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | src/parser.rs | 23 | ||||
-rw-r--r-- | src/serialization.rs | 86 |
3 files changed, 96 insertions, 19 deletions
@@ -1,6 +1,6 @@ -RUSTC := rustc -RUSTDOC := rustdoc -BUILD := build +RUSTC ?= rustc +RUSTDOC ?= rustdoc +BUILD ?= build LIB := $(BUILD)/$(shell $(RUSTC) --crate-file-name src/toml.rs) TEST := $(BUILD)/tomltest diff --git a/src/parser.rs b/src/parser.rs index 29de39b..f97645d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -406,12 +406,12 @@ impl<'a> Parser<'a> { fn boolean(&mut self, start: uint) -> Option<Value> { let rest = self.input.slice_from(start); if rest.starts_with("true") { - for _ in range(0, 4) { + for _ in range(0u, 4u) { self.cur.next(); } Some(Boolean(true)) } else if rest.starts_with("false") { - for _ in range(0, 5) { + for _ in range(0u, 5u) { self.cur.next(); } Some(Boolean(false)) @@ -429,7 +429,7 @@ impl<'a> Parser<'a> { fn datetime(&mut self, start: uint, end_so_far: uint) -> Option<Value> { let mut date = self.input.slice(start, end_so_far).to_string(); - for _ in range(0, 15) { + for _ in range(0u, 15u) { match self.cur.next() { Some((_, ch)) => date.push_char(ch), None => { @@ -684,6 +684,23 @@ mod tests { use super::Parser; #[test] + fn crlf() { + let mut p = Parser::new("\ +[project]\r\n\ +\r\n\ +name = \"splay\"\r\n\ +version = \"0.1.0\"\r\n\ +authors = [\"alex@crichton.co\"]\r\n\ +\r\n\ +[[lib]]\r\n\ +\r\n\ +path = \"lib.rs\"\r\n\ +name = \"splay\"\r\n\ +"); + assert!(p.parse().is_some()); + } + + #[test] fn linecol() { let p = Parser::new("ab\ncde\nf"); assert_eq!(p.to_linecol(0), (0, 0)); diff --git a/src/serialization.rs b/src/serialization.rs index 7011eb6..26fc7ba 100644 --- a/src/serialization.rs +++ b/src/serialization.rs @@ -48,7 +48,9 @@ pub struct Encoder { /// `Decodable` types to be generated by this decoder. The input is any /// arbitrary TOML value. pub struct Decoder { - toml: Option<Value>, + /// The TOML value left over after decoding. This can be used to inspect + /// whether fields were decoded or not. + pub toml: Option<Value>, cur_field: Option<String>, } @@ -403,10 +405,12 @@ impl Decoder { impl serialize::Decoder<DecodeError> 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<uint, DecodeError> { self.read_i64().map(|i| i as uint) @@ -428,7 +432,7 @@ impl serialize::Decoder<DecodeError> for Decoder { } fn read_i64(&mut self) -> Result<i64, DecodeError> { 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 +447,7 @@ impl serialize::Decoder<DecodeError> for Decoder { } fn read_bool(&mut self) -> Result<bool, DecodeError> { 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 +461,22 @@ impl serialize::Decoder<DecodeError> for Decoder { self.read_f64().map(|f| f as f32) } 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 => - 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<String, DecodeError> { 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 +545,21 @@ impl serialize::Decoder<DecodeError> for Decoder { _f_idx: uint, f: |&mut Decoder| -> Result<T, DecodeError>) -> Result<T, DecodeError> { + 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<T>(&mut self, @@ -957,4 +977,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) + }) + }))); + } } |