aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Titus Wormer <tituswormer@gmail.com>2022-07-19 10:54:32 +0200
committerLibravatar Titus Wormer <tituswormer@gmail.com>2022-07-19 10:54:32 +0200
commitf18bcde990944af345ab8d1dedd99d826708792b (patch)
treed85efdd4f0e54206d0c9d848465770b9c0d872e8 /src
parent1f9433d9f591b8a6193f215113b97e174b850e62 (diff)
downloadmarkdown-rs-f18bcde990944af345ab8d1dedd99d826708792b.tar.gz
markdown-rs-f18bcde990944af345ab8d1dedd99d826708792b.tar.bz2
markdown-rs-f18bcde990944af345ab8d1dedd99d826708792b.zip
Fix performance around a lot of lists
Diffstat (limited to 'src')
-rw-r--r--src/construct/list.rs49
1 files changed, 33 insertions, 16 deletions
diff --git a/src/construct/list.rs b/src/construct/list.rs
index 5fd0849..9cd3b62 100644
--- a/src/construct/list.rs
+++ b/src/construct/list.rs
@@ -418,19 +418,18 @@ pub fn resolve_list_item(tokenizer: &mut Tokenizer) -> Vec<Event> {
while list_index > 0 {
list_index -= 1;
let previous = &lists_wip[list_index];
- if previous.0 == current.0
- && previous.1 == current.1
- && skip::opt(
- &tokenizer.events,
- previous.3 + 1,
- &[
- Token::SpaceOrTab,
- Token::LineEnding,
- Token::BlankLineEnding,
- Token::BlockQuotePrefix,
- ],
- ) == current.2
- {
+ let before = skip::opt(
+ &tokenizer.events,
+ previous.3 + 1,
+ &[
+ Token::SpaceOrTab,
+ Token::LineEnding,
+ Token::BlankLineEnding,
+ Token::BlockQuotePrefix,
+ ],
+ );
+
+ if previous.0 == current.0 && previous.1 == current.1 && before == current.2 {
let previous_mut = &mut lists_wip[list_index];
previous_mut.3 = current.3;
let mut remainder = lists_wip.drain((list_index + 1)..).collect::<Vec<_>>();
@@ -438,12 +437,30 @@ pub fn resolve_list_item(tokenizer: &mut Tokenizer) -> Vec<Event> {
matched = true;
break;
}
-
- // To do: move items that could never match anymore over to `lists`,
- // This currently keeps on growing and growing!
}
if !matched {
+ let mut index = lists_wip.len();
+ let mut exit: Option<usize> = None;
+
+ while index > 0 {
+ index -= 1;
+
+ // If the current (new) item starts after where this
+ // item on the stack ends, we can remove it from the
+ // stack.
+ if current.2 > lists_wip[index].3 {
+ exit = Some(index);
+ } else {
+ break;
+ }
+ }
+
+ if let Some(exit) = exit {
+ let mut remainder = lists_wip.drain(exit..).collect::<Vec<_>>();
+ lists.append(&mut remainder);
+ }
+
lists_wip.push(current);
}