diff --git a/src/lib.rs b/src/lib.rs index a38fb62..882fecf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,6 +69,19 @@ pub struct JSON { i: usize, } +/// Cut down the if boilerplate +/// +/// Thanks to `uwaterloodudette` on reddit +macro_rules! try_parse { + ($( $e:expr ),* ) => { + $( + if let Some(v) = $e? { + return Ok(v); + } + )* + }; +} + impl JSON { /// Private constructor fn new(json: &str) -> Self { @@ -82,34 +95,22 @@ impl JSON { fn parse_value(&mut self) -> Result { self.skip_whitespace(); - return if let Some(string) = self.parse_string()? { - Ok(string) - } else if let Some(number) = self.parse_number()? { - Ok(number) - } else if let Some(object) = self.parse_object()? { - Ok(object) - } else if let Some(array) = self.parse_array()? { - Ok(array) - } else if let Some(t) = self.parse_keyword("true", JSONValue::True)? { - Ok(t) - } else if let Some(f) = self.parse_keyword("false", JSONValue::False)? { - Ok(f) - } else if let Some(n) = self.parse_keyword("null", JSONValue::Null)? { - Ok(n) - } else { - Err(ParseError::UnexpectedEndOfInput(String::from( - "Doesn't seem to be valid JSON", - ))) - }; + // Go through the parser methods, until you find + // one that doesn't return a `None` + try_parse!( + self.parse_string(), + self.parse_number(), + self.parse_object(), + self.parse_array(), + self.parse_keyword("true", JSONValue::True), + self.parse_keyword("false", JSONValue::False), + self.parse_keyword("null", JSONValue::Null) + ); - // Eagerly evaluated simpler alternative to the original option iterator chain - // let value = self.parse_string()? - // .or(self.parse_number()?) - // .or(self.parse_object()?) - // .or(self.parse_array()?) - // .or(self.parse_keyword("true", JSONValue::True)?) - // .or(self.parse_keyword("false", JSONValue::False)?) - // .or(self.parse_keyword("null", JSONValue::Null)?); + // Every parser failed, so the syntax is probably incorrect + Err(ParseError::UnexpectedEndOfInput(String::from( + "Doesn't seem to be valid JSON", + ))) } /// See if there's a `JSONValue::Object` next in the JSON @@ -143,7 +144,7 @@ impl JSON { JSONValue::String(s) => s, _ => panic!("parse_string returned non-string value"), }, - None => panic!("Missing object key"), + None => String::new(), }; self.skip_whitespace();