aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzriel Hoh <azriel91@gmail.com>2018-10-20 16:24:16 +1300
committerAzriel Hoh <azriel91@gmail.com>2018-11-10 11:07:26 +1300
commit8fc8a6a5ca872022b9412003a7ce90f0dce76f9c (patch)
treeecbd2d25efbcf72bdd75b8ef62e88f6f269fd6be
parent9ce37a6b0278d4c422e5cac7003cf908cc2c9e3f (diff)
downloadmilf-rs-8fc8a6a5ca872022b9412003a7ce90f0dce76f9c.tar.gz
milf-rs-8fc8a6a5ca872022b9412003a7ce90f0dce76f9c.zip
Better error handling when parsing tuples.
Issue #225
-rw-r--r--src/de.rs47
1 files changed, 35 insertions, 12 deletions
diff --git a/src/de.rs b/src/de.rs
index 4f5a5f2..810b85b 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -162,9 +162,19 @@ enum ErrorKind {
/// A struct was expected but something else was found
ExpectedString,
- /// A tuple with a certain number of elements was expected but something else was found
+ /// A tuple with a certain number of elements was expected but something
+ /// else was found.
ExpectedTuple(usize),
+ /// Expected table keys to be in increasing tuple index order, but something
+ /// else was found.
+ ExpectedTupleIndex {
+ /// Expected index.
+ expected: usize,
+ /// Key that was specified.
+ found: String,
+ },
+
/// An empty table was expected but entries were found
ExpectedEmptyTable,
@@ -812,16 +822,24 @@ impl<'de> de::VariantAccess<'de> for InlineTableDeserializer<'de> {
let tuple_values = values
.into_iter()
.enumerate()
- .filter_map(|(index, (key, value))| {
- // TODO: Is this expensive?
- if key == format!("{}", index) {
- Some(value)
- } else {
- // TODO: Err()
- unimplemented!()
- }
+ .map(|(index, (key, value))| match key.parse::<usize>() {
+ Ok(key_index) if key_index == index => Ok(value),
+ Ok(_) | Err(_) => Err(Error::from_kind(ErrorKind::ExpectedTupleIndex {
+ expected: index,
+ found: key.to_string(),
+ })),
})
- .collect::<Vec<_>>(); // TODO: is this expensive?
+ // Fold all values into a `Vec`, or return the first error.
+ .fold(Ok(Vec::with_capacity(len)), |result, value_result| {
+ result.and_then(|mut tuple_values| match value_result {
+ Ok(value) => {
+ tuple_values.push(value);
+ Ok(tuple_values)
+ }
+ // `Result<de::Value, Self::Error>` to `Result<Vec<_>, Self::Error>`
+ Err(e) => Err(e),
+ })
+ })?;
if tuple_values.len() == len {
de::Deserializer::deserialize_seq(
@@ -1521,7 +1539,11 @@ impl fmt::Display for Error {
ErrorKind::MultilineStringKey => "multiline strings are not allowed for key".fmt(f)?,
ErrorKind::Custom => self.inner.message.fmt(f)?,
ErrorKind::ExpectedString => "expected string".fmt(f)?,
- ErrorKind::ExpectedTuple(l) => write!(f, "expected tuple with length {}", l)?,
+ ErrorKind::ExpectedTuple(l) => write!(f, "expected table with length {}", l)?,
+ ErrorKind::ExpectedTupleIndex {
+ expected,
+ ref found,
+ } => write!(f, "expected table key `{}`, but was `{}`", expected, found)?,
ErrorKind::ExpectedEmptyTable => "expected empty table".fmt(f)?,
ErrorKind::DottedKeyInvalidType => {
"dotted key attempted to extend non-table type".fmt(f)?
@@ -1570,7 +1592,8 @@ impl error::Error for Error {
ErrorKind::MultilineStringKey => "invalid multiline string for key",
ErrorKind::Custom => "a custom error",
ErrorKind::ExpectedString => "expected string",
- ErrorKind::ExpectedTuple(_) => "expected tuple",
+ ErrorKind::ExpectedTuple(_) => "expected table length",
+ ErrorKind::ExpectedTupleIndex { .. } => "expected table key",
ErrorKind::ExpectedEmptyTable => "expected empty table",
ErrorKind::DottedKeyInvalidType => "dotted key invalid type",
ErrorKind::__Nonexhaustive => panic!(),