Do not parse the lesser block contents during parsing, but rather only if the contents are requested.
Some checks failed
rust-test Build rust-test has failed
clippy Build clippy has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded

This seemed like an unnecessary allocation during parsing, especially considering we throw away some parses based on whether or not we found radio targets in the source.
This commit is contained in:
Tom Alexander
2023-10-31 18:13:21 -04:00
parent 93cfa71df2
commit a5627d0cee
3 changed files with 124 additions and 82 deletions

View File

@@ -1,5 +1,3 @@
use std::borrow::Cow;
use nom::branch::alt;
use nom::bytes::complete::is_not;
use nom::bytes::complete::tag;
@@ -204,7 +202,7 @@ where
let parser_context = parser_context.with_additional_node(&contexts[1]);
let parser_context = parser_context.with_additional_node(&contexts[2]);
let (remaining, contents) = content(&parser_context, remaining)?;
let (remaining, contents) = text_until_exit(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
@@ -238,7 +236,7 @@ where
retain_labels,
use_labels,
label_format,
contents,
contents: Into::<&str>::into(contents),
},
))
}
@@ -278,7 +276,7 @@ where
let parser_context = parser_context.with_additional_node(&contexts[1]);
let parser_context = parser_context.with_additional_node(&contexts[2]);
let (remaining, contents) = content(&parser_context, remaining)?;
let (remaining, contents) = text_until_exit(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
@@ -294,7 +292,7 @@ where
),
export_type: export_type.map(Into::<&str>::into),
data: parameters.map(Into::<&str>::into),
contents,
contents: Into::<&str>::into(contents),
},
))
}
@@ -333,7 +331,7 @@ where
let parser_context = context.with_additional_node(&contexts[0]);
let parser_context = parser_context.with_additional_node(&contexts[1]);
let parser_context = parser_context.with_additional_node(&contexts[2]);
let (remaining, contents) = content(&parser_context, remaining)?;
let (remaining, contents) = text_until_exit(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
@@ -373,7 +371,7 @@ where
retain_labels,
use_labels,
label_format,
contents,
contents: Into::<&str>::into(contents),
},
))
}
@@ -652,71 +650,3 @@ fn switch_word<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
is_not(" \t\r\n"),
))(input)
}
enum ContentState {
Normal,
Modified(String),
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(ret, level = "debug", skip(context))
)]
pub(crate) fn content<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Cow<'s, str>> {
let mut state = ContentState::Normal;
let mut remaining = input;
let exit_matcher_parser = parser_with_context!(exit_matcher_parser)(context);
loop {
if exit_matcher_parser(remaining).is_ok() {
break;
}
let (remain, (pre_escape_whitespace, line)) = content_line(remaining)?;
if let Some(val) = pre_escape_whitespace {
if let ContentState::Modified(ref mut ret) = state {
ret.push_str(Into::<&str>::into(val));
} else {
let mut ret = String::new();
ret.push_str(Into::<&str>::into(input.get_until(remaining)));
ret.push_str(Into::<&str>::into(val));
state = ContentState::Modified(ret);
}
}
if let ContentState::Modified(ref mut ret) = state {
ret.push_str(line.into());
}
remaining = remain;
}
match state {
ContentState::Normal => Ok((
remaining,
Cow::Borrowed(Into::<&str>::into(input.get_until(remaining))),
)),
ContentState::Modified(ret) => Ok((remaining, Cow::Owned(ret))),
}
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn content_line<'s>(
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, (Option<OrgSource<'s>>, OrgSource<'s>)> {
let (remaining, pre_escape_whitespace) = opt(map(
tuple((
recognize(tuple((
space0,
many_till(
tag(","),
peek(tuple((tag(","), alt((tag("#+"), tag("*")))))),
),
))),
tag(","),
)),
|(pre_comma, _)| pre_comma,
))(input)?;
let (remaining, line_post_escape) = recognize(many_till(anychar, line_ending))(remaining)?;
Ok((remaining, (pre_escape_whitespace, line_post_escape)))
}