Skip to content

Commit fb83c29

Browse files
authored
Merge pull request #772 from epage/array
perf(parser): Optimize array parsing
2 parents d507db2 + e273be6 commit fb83c29

File tree

1 file changed

+26
-28
lines changed

1 file changed

+26
-28
lines changed

crates/toml_edit/src/parser/array.rs

+26-28
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use winnow::combinator::cut_err;
22
use winnow::combinator::delimited;
33
use winnow::combinator::opt;
4+
use winnow::combinator::peek;
45
use winnow::combinator::separated;
56
use winnow::combinator::trace;
67

78
use crate::parser::trivia::ws_comment_newline;
89
use crate::parser::value::value;
9-
use crate::{Array, Item, RawString, Value};
10+
use crate::{Array, Item, RawString};
1011

1112
use crate::parser::prelude::*;
1213

@@ -36,36 +37,33 @@ const ARRAY_CLOSE: u8 = b']';
3637
// array-sep = ws %x2C ws ; , Comma
3738
const ARRAY_SEP: u8 = b',';
3839

39-
// note: this rule is modified
40-
// array-values = [ ( array-value array-sep array-values ) /
41-
// array-value / ws-comment-newline ]
40+
// array-values = ws-comment-newline val ws-comment-newline array-sep array-values
41+
// array-values =/ ws-comment-newline val ws-comment-newline [ array-sep ]
4242
pub(crate) fn array_values(input: &mut Input<'_>) -> PResult<Array> {
43-
(
44-
opt(
45-
(separated(1.., array_value, ARRAY_SEP), opt(ARRAY_SEP)).map(
46-
|(v, trailing): (Vec<Value>, Option<u8>)| {
47-
(
48-
Array::with_vec(v.into_iter().map(Item::Value).collect()),
49-
trailing.is_some(),
50-
)
51-
},
52-
),
53-
),
54-
ws_comment_newline.span(),
55-
)
56-
.try_map::<_, _, std::str::Utf8Error>(|(array, trailing)| {
57-
let (mut array, comma) = array.unwrap_or_default();
58-
array.set_trailing_comma(comma);
59-
array.set_trailing(RawString::with_span(trailing));
60-
Ok(array)
61-
})
62-
.parse_next(input)
43+
if peek(opt(ARRAY_CLOSE)).parse_next(input)?.is_some() {
44+
// Optimize for empty arrays, avoiding `value` from being expected to fail
45+
return Ok(Array::new());
46+
}
47+
48+
let array = separated(0.., array_value, ARRAY_SEP).parse_next(input)?;
49+
let mut array = Array::with_vec(array);
50+
if !array.is_empty() {
51+
let comma = opt(ARRAY_SEP).parse_next(input)?.is_some();
52+
array.set_trailing_comma(comma);
53+
}
54+
let trailing = ws_comment_newline.span().parse_next(input)?;
55+
array.set_trailing(RawString::with_span(trailing));
56+
57+
Ok(array)
6358
}
6459

65-
pub(crate) fn array_value(input: &mut Input<'_>) -> PResult<Value> {
66-
(ws_comment_newline.span(), value, ws_comment_newline.span())
67-
.map(|(ws1, v, ws2)| v.decorated(RawString::with_span(ws1), RawString::with_span(ws2)))
68-
.parse_next(input)
60+
pub(crate) fn array_value(input: &mut Input<'_>) -> PResult<Item> {
61+
let prefix = ws_comment_newline.span().parse_next(input)?;
62+
let value = value.parse_next(input)?;
63+
let suffix = ws_comment_newline.span().parse_next(input)?;
64+
let value = value.decorated(RawString::with_span(prefix), RawString::with_span(suffix));
65+
let value = Item::Value(value);
66+
Ok(value)
6967
}
7068

7169
#[cfg(test)]

0 commit comments

Comments
 (0)