This should provide more meaningful errors to the user and is somewhat closer to how I would expect a parser to work in a situation like this (ie we should ensure `cut` errors get propagated). The main risk is if there is any error recovery meant to be going on.
Unified · Split
| @@ -121,10 +121,7 @@ fn section<'i>( · 120 unmodified lines | |||
| 121 | dispatch(Event::Newline(Cow::Borrowed(v.as_bstr()))); | 121 | dispatch(Event::Newline(Cow::Borrowed(v.as_bstr()))); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | let before_key = i.checkpoint(); | 124 | key_value_pair(i, node, dispatch)?; |
| 125 | if key_value_pair(i, node, dispatch).is_err() { | ||
| 126 | i.reset(before_key); | ||
| 127 | } | ||
| 128 | 125 | ||
| 129 | if let Some(comment) = opt(comment).parse_next(i)? { | 126 | if let Some(comment) = opt(comment).parse_next(i)? { |
| 130 | dispatch(Event::Comment(comment)); | 127 | dispatch(Event::Comment(comment)); |
| @@ -216,16 +213,18 @@ fn key_value_pair<'i>( · 85 unmodified lines | |||
| 216 | dispatch: &mut impl FnMut(Event<'i>), | 213 | dispatch: &mut impl FnMut(Event<'i>), |
| 217 | ) -> PResult<(), NomError<&'i [u8]>> { | 214 | ) -> PResult<(), NomError<&'i [u8]>> { |
| 218 | *node = ParseNode::Name; | 215 | *node = ParseNode::Name; |
| 219 | let name = config_name.parse_next(i)?; | 216 | if let Some(name) = opt(config_name).parse_next(i)? { |
| 217 | dispatch(Event::SectionKey(section::Key(Cow::Borrowed(name)))); | ||
| 220 | 218 | ||
| 221 | dispatch(Event::SectionKey(section::Key(Cow::Borrowed(name)))); | 219 | if let Some(whitespace) = opt(take_spaces1).parse_next(i)? { |
| 220 | dispatch(Event::Whitespace(Cow::Borrowed(whitespace))); | ||
| 221 | } | ||
| 222 | 222 | ||
| 223 | if let Some(whitespace) = opt(take_spaces1).parse_next(i)? { | 223 | *node = ParseNode::Value; |
| 224 | dispatch(Event::Whitespace(Cow::Borrowed(whitespace))); | 224 | config_value(i, dispatch) |
| 225 | } else { | ||
| 226 | Ok(()) | ||
| 225 | } | 227 | } |
| 226 | |||
| 227 | *node = ParseNode::Value; | ||
| 228 | config_value(i, dispatch) | ||
| 229 | } | 228 | } |
| 230 | 229 | ||
| 231 | /// Parses the config name of a config pair. Assumes the input has already been | 230 | /// Parses the config name of a config pair. Assumes the input has already been |
| @@ -808,7 +808,12 @@ mod key_value_pair { · 807 unmodified lines | |||
| 808 | fn nonascii_is_allowed_for_values_but_not_for_keys() { | 808 | fn nonascii_is_allowed_for_values_but_not_for_keys() { |
| 809 | let mut node = ParseNode::SectionHeader; | 809 | let mut node = ParseNode::SectionHeader; |
| 810 | let mut vec = Default::default(); | 810 | let mut vec = Default::default(); |
| 811 | assert!(key_value("你好".as_bytes(), &mut node, &mut vec).is_err()); | 811 | // Verifying `is_ok` because bad keys get ignored |
| 812 | assert!(key_value("你好".as_bytes(), &mut node, &mut vec).is_ok()); | ||
| 813 | assert_eq!(vec, into_events(vec![])); | ||
| 814 | |||
| 815 | let mut node = ParseNode::SectionHeader; | ||
| 816 | let mut vec = Default::default(); | ||
| 812 | assert!(key_value("a = 你好 ".as_bytes(), &mut node, &mut vec).is_ok()); | 817 | assert!(key_value("a = 你好 ".as_bytes(), &mut node, &mut vec).is_ok()); |
| 813 | assert_eq!( | 818 | assert_eq!( |
| 814 | vec, | 819 | vec, |