aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--src/parser.rs23
-rw-r--r--src/serialization.rs86
3 files changed, 96 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index 4500730..3f60516 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
+ })
+ })));
+ }
}