Skip to content

Commit e208362

Browse files
committed
Improve inner loop of config value parsing
I found this cut in half from the performance issue from fe997c8. I'm assuming for less degenerate cases it will still offer performance improvements.
1 parent 510192e commit e208362

File tree

1 file changed

+50
-45
lines changed
  • gix-config/src/parse/nom

1 file changed

+50
-45
lines changed

gix-config/src/parse/nom/mod.rs

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -265,62 +265,67 @@ fn value_impl<'i>(i: &mut &'i [u8], dispatch: &mut impl FnMut(Event<'i>)) -> PRe
265265
// Used to determine if we return a Value or Value{Not,}Done
266266
let mut partial_value_found = false;
267267

268-
while let Some(c) = i.next_token() {
269-
match c {
270-
b'\n' => {
271-
value_end = Some(i.offset_from(&value_start_checkpoint) - 1);
272-
break;
273-
}
274-
b';' | b'#' if !is_in_quotes => {
275-
value_end = Some(i.offset_from(&value_start_checkpoint) - 1);
276-
break;
277-
}
278-
b'\\' => {
279-
let escaped_index = i.offset_from(&value_start_checkpoint);
280-
let escape_index = escaped_index - 1;
281-
let Some(mut c) = i.next_token() else {
282-
i.reset(start_checkpoint);
283-
return Err(winnow::error::ErrMode::from_error_kind(i, ErrorKind::Token));
284-
};
285-
let mut consumed = 1;
286-
if c == b'\r' {
287-
c = i.next_token().ok_or_else(|| {
288-
i.reset(start_checkpoint);
289-
winnow::error::ErrMode::from_error_kind(i, ErrorKind::Token)
290-
})?;
291-
if c != b'\n' {
268+
loop {
269+
let _ = take_while(0.., |c| !matches!(c, b'\n' | b'\\' | b'"' | b';' | b'#')).parse_next(i)?;
270+
if let Some(c) = i.next_token() {
271+
match c {
272+
b'\n' => {
273+
value_end = Some(i.offset_from(&value_start_checkpoint) - 1);
274+
break;
275+
}
276+
b';' | b'#' if !is_in_quotes => {
277+
value_end = Some(i.offset_from(&value_start_checkpoint) - 1);
278+
break;
279+
}
280+
b'\\' => {
281+
let escaped_index = i.offset_from(&value_start_checkpoint);
282+
let escape_index = escaped_index - 1;
283+
let Some(mut c) = i.next_token() else {
292284
i.reset(start_checkpoint);
293-
return Err(winnow::error::ErrMode::from_error_kind(i, ErrorKind::Slice));
285+
return Err(winnow::error::ErrMode::from_error_kind(i, ErrorKind::Token));
286+
};
287+
let mut consumed = 1;
288+
if c == b'\r' {
289+
c = i.next_token().ok_or_else(|| {
290+
i.reset(start_checkpoint);
291+
winnow::error::ErrMode::from_error_kind(i, ErrorKind::Token)
292+
})?;
293+
if c != b'\n' {
294+
i.reset(start_checkpoint);
295+
return Err(winnow::error::ErrMode::from_error_kind(i, ErrorKind::Slice));
296+
}
297+
consumed += 1;
294298
}
295-
consumed += 1;
296-
}
297299

298-
match c {
299-
b'\n' => {
300-
partial_value_found = true;
300+
match c {
301+
b'\n' => {
302+
partial_value_found = true;
301303

302-
i.reset(value_start_checkpoint);
304+
i.reset(value_start_checkpoint);
303305

304-
let value = i.next_slice(escape_index).as_bstr();
305-
dispatch(Event::ValueNotDone(Cow::Borrowed(value)));
306+
let value = i.next_slice(escape_index).as_bstr();
307+
dispatch(Event::ValueNotDone(Cow::Borrowed(value)));
306308

307-
i.next_token();
309+
i.next_token();
308310

309-
let nl = i.next_slice(consumed).as_bstr();
310-
dispatch(Event::Newline(Cow::Borrowed(nl)));
311+
let nl = i.next_slice(consumed).as_bstr();
312+
dispatch(Event::Newline(Cow::Borrowed(nl)));
311313

312-
value_start_checkpoint = i.checkpoint();
313-
value_end = None;
314-
}
315-
b'n' | b't' | b'\\' | b'b' | b'"' => {}
316-
_ => {
317-
i.reset(start_checkpoint);
318-
return Err(winnow::error::ErrMode::from_error_kind(i, ErrorKind::Token));
314+
value_start_checkpoint = i.checkpoint();
315+
value_end = None;
316+
}
317+
b'n' | b't' | b'\\' | b'b' | b'"' => {}
318+
_ => {
319+
i.reset(start_checkpoint);
320+
return Err(winnow::error::ErrMode::from_error_kind(i, ErrorKind::Token));
321+
}
319322
}
320323
}
324+
b'"' => is_in_quotes = !is_in_quotes,
325+
_ => {}
321326
}
322-
b'"' => is_in_quotes = !is_in_quotes,
323-
_ => {}
327+
} else {
328+
break;
324329
}
325330
}
326331
if is_in_quotes {

0 commit comments

Comments
 (0)