use mut vec reference

This commit is contained in:
Edward Shen 2021-02-26 19:30:04 -05:00
parent 6b8386d449
commit 17ba292934
Signed by: edward
GPG key ID: 19182661E818369F

View file

@ -631,34 +631,56 @@ fn section<'a, 'b>(
i: &'a [u8], i: &'a [u8],
node: &'b mut ParserNode, node: &'b mut ParserNode,
) -> IResult<&'a [u8], (ParsedSection<'a>, usize)> { ) -> IResult<&'a [u8], (ParsedSection<'a>, usize)> {
let (i, section_header) = section_header(i)?; let (mut i, section_header) = section_header(i)?;
let mut newlines = 0; let mut newlines = 0;
let (i, items) = many0(alt(( let mut items = vec![];
map(take_spaces, |space| {
vec![Event::Whitespace(Cow::Borrowed(space.into()))] // This would usually be a many0(alt(...)), the manual loop allows us to
}), // optimize vec insertions
map(take_newline, |(newline, counter)| { loop {
newlines += counter; let old_i = i;
vec![Event::Newline(Cow::Borrowed(newline.into()))]
}), if let Ok((new_i, v)) = take_spaces(i) {
map( if old_i != new_i {
|i| section_body(i, node), i = new_i;
|(key, values)| { items.push(Event::Whitespace(Cow::Borrowed(v.into())));
let mut vec = vec![Event::Key(Cow::Borrowed(key.into()))]; }
vec.extend(values); }
vec
}, if let Ok((new_i, (v, new_newlines))) = take_newline(i) {
), if old_i != new_i {
map(comment, |comment| vec![Event::Comment(comment)]), i = new_i;
)))(i)?; newlines += new_newlines;
items.push(Event::Newline(Cow::Borrowed(v.into())));
}
}
if let Ok((new_i, _)) = section_body(i, node, &mut items) {
if old_i != new_i {
i = new_i;
// items.push(Event::Key(Cow::Borrowed(key.into())));
}
}
if let Ok((new_i, comment)) = comment(i) {
if old_i != new_i {
i = new_i;
items.push(Event::Comment(comment));
}
}
if old_i == i {
break;
}
}
Ok(( Ok((
i, i,
( (
ParsedSection { ParsedSection {
section_header, section_header,
events: items.into_iter().flatten().collect(), events: items,
}, },
newlines, newlines,
), ),
@ -716,26 +738,26 @@ fn section_header(i: &[u8]) -> IResult<&[u8], ParsedSectionHeader> {
)) ))
} }
fn section_body<'a, 'b>( fn section_body<'a, 'b, 'c>(
i: &'a [u8], i: &'a [u8],
node: &'b mut ParserNode, node: &'b mut ParserNode,
) -> IResult<&'a [u8], (&'a [u8], Vec<Event<'a>>)> { items: &'c mut Vec<Event<'a>>,
) -> IResult<&'a [u8], ()> {
// maybe need to check for [ here // maybe need to check for [ here
*node = ParserNode::ConfigName; *node = ParserNode::ConfigName;
let (i, name) = config_name(i)?; let (i, name) = config_name(i)?;
items.push(Event::Key(Cow::Borrowed(name.into())));
let (i, whitespace) = opt(take_spaces)(i)?; let (i, whitespace) = opt(take_spaces)(i)?;
*node = ParserNode::ConfigValue;
let (i, value) = config_value(i)?;
if let Some(whitespace) = whitespace { if let Some(whitespace) = whitespace {
let mut events = vec![Event::Whitespace(Cow::Borrowed(whitespace.into()))]; items.push(Event::Whitespace(Cow::Borrowed(whitespace.into())));
events.extend(value);
Ok((i, (name, events)))
} else {
Ok((i, (name, value)))
} }
*node = ParserNode::ConfigValue;
let (i, _) = config_value(i, items)?;
Ok((i, ()))
} }
/// Parses the config name of a config pair. Assumes the input has already been /// Parses the config name of a config pair. Assumes the input has already been
@ -757,24 +779,22 @@ fn config_name(i: &[u8]) -> IResult<&[u8], &[u8]> {
take_while(|c: u8| (c as char).is_alphanumeric() || c == b'-')(i) take_while(|c: u8| (c as char).is_alphanumeric() || c == b'-')(i)
} }
fn config_value(i: &[u8]) -> IResult<&[u8], Vec<Event>> { fn config_value<'a, 'b>(i: &'a [u8], events: &'b mut Vec<Event<'a>>) -> IResult<&'a [u8], ()> {
if let (i, Some(_)) = opt(char('='))(i)? { if let (i, Some(_)) = opt(char('='))(i)? {
let mut events = vec![];
events.push(Event::KeyValueSeparator); events.push(Event::KeyValueSeparator);
let (i, whitespace) = opt(take_spaces)(i)?; let (i, whitespace) = opt(take_spaces)(i)?;
let (i, values) = value_impl(i)?;
if let Some(whitespace) = whitespace { if let Some(whitespace) = whitespace {
events.push(Event::Whitespace(Cow::Borrowed(whitespace.into()))); events.push(Event::Whitespace(Cow::Borrowed(whitespace.into())));
} }
events.extend(values); let (i, _) = value_impl(i, events)?;
Ok((i, events)) Ok((i, ()))
} else { } else {
Ok((i, vec![Event::Value(Cow::Borrowed("".into()))])) events.push(Event::Value(Cow::Borrowed("".into())));
Ok((i, ()))
} }
} }
fn value_impl(i: &[u8]) -> IResult<&[u8], Vec<Event>> { fn value_impl<'a, 'b>(i: &'a [u8], events: &'b mut Vec<Event<'a>>) -> IResult<&'a [u8], ()> {
let mut events = vec![];
let mut parsed_index: usize = 0; let mut parsed_index: usize = 0;
let mut offset: usize = 0; let mut offset: usize = 0;
@ -861,7 +881,7 @@ fn value_impl(i: &[u8]) -> IResult<&[u8], Vec<Event>> {
events.push(Event::Value(Cow::Borrowed(remainder_value.into()))); events.push(Event::Value(Cow::Borrowed(remainder_value.into())));
} }
Ok((i, events)) Ok((i, ()))
} }
fn take_spaces(i: &[u8]) -> IResult<&[u8], &[u8]> { fn take_spaces(i: &[u8]) -> IResult<&[u8], &[u8]> {
@ -1020,32 +1040,33 @@ mod config_name {
#[cfg(test)] #[cfg(test)]
mod section_body { mod section_body {
use super::*; use super::*;
use crate::test_util::{value_event, whitespace_event}; use crate::test_util::{name_event, value_event, whitespace_event};
#[test] #[test]
fn whitespace_is_not_ambigious() { fn whitespace_is_not_ambigious() {
let mut node = ParserNode::SectionHeader; let mut node = ParserNode::SectionHeader;
let mut vec = vec![];
assert!(section_body(b"a =b", &mut node, &mut vec).is_ok());
assert_eq!( assert_eq!(
section_body(b"a =b", &mut node).unwrap().1, vec,
(
"a".as_bytes(),
vec![ vec![
name_event("a"),
whitespace_event(" "), whitespace_event(" "),
Event::KeyValueSeparator, Event::KeyValueSeparator,
value_event("b") value_event("b")
] ]
)
); );
let mut vec = vec![];
assert!(section_body(b"a= b", &mut node, &mut vec).is_ok());
assert_eq!( assert_eq!(
section_body(b"a= b", &mut node).unwrap().1, vec,
(
"a".as_bytes(),
vec![ vec![
name_event("a"),
Event::KeyValueSeparator, Event::KeyValueSeparator,
whitespace_event(" "), whitespace_event(" "),
value_event("b") value_event("b")
] ]
)
); );
} }
} }
@ -1053,117 +1074,148 @@ mod section_body {
#[cfg(test)] #[cfg(test)]
mod value_no_continuation { mod value_no_continuation {
use super::*; use super::*;
use crate::test_util::{fully_consumed, value_event}; use crate::test_util::value_event;
#[test] #[test]
fn no_comment() { fn no_comment() {
assert_eq!( let mut events = vec![];
value_impl(b"hello").unwrap(), assert_eq!(value_impl(b"hello", &mut events).unwrap().0, b"");
fully_consumed(vec![value_event("hello")]) assert_eq!(events, vec![value_event("hello")]);
);
} }
#[test] #[test]
fn no_comment_newline() { fn no_comment_newline() {
assert_eq!( let mut events = vec![];
value_impl(b"hello\na").unwrap(), assert_eq!(value_impl(b"hello\na", &mut events).unwrap().0, b"\na");
("\na".as_bytes(), vec![value_event("hello")]) assert_eq!(events, vec![value_event("hello")]);
)
} }
#[test] #[test]
fn semicolon_comment_not_consumed() { fn semicolon_comment_not_consumed() {
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(b"hello;world").unwrap(), value_impl(b"hello;world", &mut events).unwrap().0,
(";world".as_bytes(), vec![value_event("hello"),]) b";world"
); );
assert_eq!(events, vec![value_event("hello")]);
} }
#[test] #[test]
fn octothorpe_comment_not_consumed() { fn octothorpe_comment_not_consumed() {
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(b"hello#world").unwrap(), value_impl(b"hello#world", &mut events).unwrap().0,
("#world".as_bytes(), vec![value_event("hello"),]) b"#world"
); );
assert_eq!(events, vec![value_event("hello")]);
} }
#[test] #[test]
fn values_with_extraneous_whitespace_without_comment() { fn values_with_extraneous_whitespace_without_comment() {
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(b"hello ").unwrap(), value_impl(b"hello ", &mut events).unwrap().0,
(" ".as_bytes(), vec![value_event("hello")]) b" "
); );
assert_eq!(events, vec![value_event("hello")]);
} }
#[test] #[test]
fn values_with_extraneous_whitespace_before_comment() { fn values_with_extraneous_whitespace_before_comment() {
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(b"hello #world").unwrap(), value_impl(b"hello #world", &mut events)
(" #world".as_bytes(), vec![value_event("hello")]) .unwrap()
.0,
b" #world"
); );
assert_eq!(events, vec![value_event("hello")]);
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(b"hello ;world").unwrap(), value_impl(b"hello ;world", &mut events)
(" ;world".as_bytes(), vec![value_event("hello")]) .unwrap()
.0,
b" ;world"
); );
assert_eq!(events, vec![value_event("hello")]);
} }
#[test] #[test]
fn trans_escaped_comment_marker_not_consumed() { fn trans_escaped_comment_marker_not_consumed() {
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(br##"hello"#"world; a"##).unwrap(), value_impl(br##"hello"#"world; a"##, &mut events).unwrap().0,
("; a".as_bytes(), vec![value_event(r##"hello"#"world"##)]) b"; a"
); );
assert_eq!(events, vec![value_event(r##"hello"#"world"##)]);
} }
#[test] #[test]
fn complex_test() { fn complex_test() {
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(br#"value";";ahhhh"#).unwrap(), value_impl(br#"value";";ahhhh"#, &mut events).unwrap().0,
(";ahhhh".as_bytes(), vec![value_event(r#"value";""#)]) b";ahhhh"
); );
assert_eq!(events, vec![value_event(r#"value";""#)]);
} }
#[test] #[test]
fn garbage_after_continution_is_err() { fn garbage_after_continution_is_err() {
assert!(value_impl(b"hello \\afwjdls").is_err()); assert!(value_impl(b"hello \\afwjdls", &mut vec![]).is_err());
} }
} }
#[cfg(test)] #[cfg(test)]
mod value_continuation { mod value_continuation {
use super::*; use super::*;
use crate::test_util::{fully_consumed, newline_event, value_done_event, value_not_done_event}; use crate::test_util::{newline_event, value_done_event, value_not_done_event};
#[test] #[test]
fn simple_continuation() { fn simple_continuation() {
let mut events = vec![];
assert_eq!(value_impl(b"hello\\\nworld", &mut events).unwrap().0, b"");
assert_eq!( assert_eq!(
value_impl(b"hello\\\nworld").unwrap(), events,
fully_consumed(vec![ vec![
value_not_done_event("hello"), value_not_done_event("hello"),
newline_event(), newline_event(),
value_done_event("world") value_done_event("world")
]) ]
); );
} }
#[test] #[test]
fn continuation_with_whitespace() { fn continuation_with_whitespace() {
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(b"hello\\\n world").unwrap(), value_impl(b"hello\\\n world", &mut events)
fully_consumed(vec![ .unwrap()
.0,
b""
);
assert_eq!(
events,
vec![
value_not_done_event("hello"), value_not_done_event("hello"),
newline_event(), newline_event(),
value_done_event(" world") value_done_event(" world")
]) ]
) );
} }
#[test] #[test]
fn complex_continuation_with_leftover_comment() { fn complex_continuation_with_leftover_comment() {
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(b"1 \"\\\"\\\na ; e \"\\\"\\\nd # \"b\t ; c").unwrap(), value_impl(b"1 \"\\\"\\\na ; e \"\\\"\\\nd # \"b\t ; c", &mut events)
( .unwrap()
" # \"b\t ; c".as_bytes(), .0,
b" # \"b\t ; c"
);
assert_eq!(
events,
vec![ vec![
value_not_done_event(r#"1 "\""#), value_not_done_event(r#"1 "\""#),
newline_event(), newline_event(),
@ -1171,23 +1223,24 @@ mod value_continuation {
newline_event(), newline_event(),
value_done_event("d") value_done_event("d")
] ]
)
); );
} }
#[test] #[test]
fn quote_split_over_two_lines_with_leftover_comment() { fn quote_split_over_two_lines_with_leftover_comment() {
let mut events = vec![];
assert_eq!( assert_eq!(
value_impl(b"\"\\\n;\";a").unwrap(), value_impl(b"\"\\\n;\";a", &mut events).unwrap().0,
( ";a".as_bytes()
";a".as_bytes(), );
assert_eq!(
events,
vec![ vec![
value_not_done_event("\""), value_not_done_event("\""),
newline_event(), newline_event(),
value_done_event(";\"") value_done_event(";\"")
] ]
) );
)
} }
} }