diff options
author | Titus Wormer <tituswormer@gmail.com> | 2022-07-18 17:24:32 +0200 |
---|---|---|
committer | Titus Wormer <tituswormer@gmail.com> | 2022-07-18 17:24:32 +0200 |
commit | d2a7c1fb0344971ac537e15d1a4b00fe18ff8c43 (patch) | |
tree | 1a9e8f889a3a0a63d0fde7fc1baf8eb3a8e6ba61 /src/content | |
parent | 7186ce91784a647b3015e04b55a95b109deceeb3 (diff) | |
download | markdown-rs-d2a7c1fb0344971ac537e15d1a4b00fe18ff8c43.tar.gz markdown-rs-d2a7c1fb0344971ac537e15d1a4b00fe18ff8c43.tar.bz2 markdown-rs-d2a7c1fb0344971ac537e15d1a4b00fe18ff8c43.zip |
Refactor to improve performance when constructs are turned off
Diffstat (limited to '')
-rw-r--r-- | src/content/string.rs | 47 | ||||
-rw-r--r-- | src/content/text.rs | 75 |
2 files changed, 73 insertions, 49 deletions
diff --git a/src/content/string.rs b/src/content/string.rs index f2650df..0a3f5eb 100644 --- a/src/content/string.rs +++ b/src/content/string.rs @@ -18,23 +18,26 @@ use crate::construct::{ }; use crate::tokenizer::{Code, State, StateFnResult, Tokenizer}; -const MARKERS: [Code; 5] = [ - // To do: build this vec based on whether they are enabled? - Code::VirtualSpace, // `whitespace` - Code::Char('\t'), // `whitespace` - Code::Char(' '), // `whitespace` - Code::Char('&'), // `character_reference` - Code::Char('\\'), // `character_escape` -]; - /// Before string. -/// -/// ```markdown -/// |& -/// |\& -/// |qwe -/// ``` pub fn start(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { + let mut markers = vec![ + Code::VirtualSpace, // `whitespace` + Code::Char('\t'), // `whitespace` + Code::Char(' '), // `hard_break_trailing`, `whitespace` + ]; + + if tokenizer.parse_state.constructs.character_reference { + markers.push(Code::Char('&')); + } + if tokenizer.parse_state.constructs.character_escape { + markers.push(Code::Char('\\')); + } + + before_marker(tokenizer, code, markers) +} + +/// Before string. +fn before_marker(tokenizer: &mut Tokenizer, code: Code, markers: Vec<Code>) -> StateFnResult { match code { Code::None => (State::Ok, None), _ => tokenizer.attempt_n( @@ -43,16 +46,16 @@ pub fn start(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { Box::new(character_escape), Box::new(whitespace), ], - |ok| Box::new(if ok { start } else { before_data }), + |ok| { + let func = if ok { before_marker } else { before_data }; + Box::new(move |t, c| func(t, c, markers)) + }, )(tokenizer, code), } } /// At data. -/// -/// ```markdown -/// |qwe -/// ``` -fn before_data(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { - tokenizer.go(|t, c| data(t, c, MARKERS.to_vec()), start)(tokenizer, code) +fn before_data(tokenizer: &mut Tokenizer, code: Code, markers: Vec<Code>) -> StateFnResult { + let copy = markers.clone(); + tokenizer.go(|t, c| data(t, c, copy), |t, c| before_marker(t, c, markers))(tokenizer, code) } diff --git a/src/content/text.rs b/src/content/text.rs index f797b11..8d63de9 100644 --- a/src/content/text.rs +++ b/src/content/text.rs @@ -29,36 +29,53 @@ use crate::construct::{ }; use crate::tokenizer::{Code, State, StateFnResult, Tokenizer}; -const MARKERS: [Code; 12] = [ - Code::VirtualSpace, // `whitespace` - Code::Char('\t'), // `whitespace` - Code::Char(' '), // `hard_break_trailing`, `whitespace` - Code::Char('!'), // `label_start_image` - Code::Char('&'), // `character_reference` - Code::Char('*'), // `attention` - Code::Char('<'), // `autolink`, `html_text` - Code::Char('['), // `label_start_link` - Code::Char('\\'), // `character_escape`, `hard_break_escape` - Code::Char(']'), // `label_end` - Code::Char('_'), // `attention` - Code::Char('`'), // `code_text` -]; - /// Before text. -/// -/// First we assume character reference. -/// -/// ```markdown -/// |& -/// |\& -/// |qwe -/// ``` pub fn start(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { + let mut markers = vec![ + Code::VirtualSpace, // `whitespace` + Code::Char('\t'), // `whitespace` + Code::Char(' '), // `hard_break_trailing`, `whitespace` + ]; + + if tokenizer.parse_state.constructs.label_start_image { + markers.push(Code::Char('!')); + } + if tokenizer.parse_state.constructs.character_reference { + markers.push(Code::Char('&')); + } + if tokenizer.parse_state.constructs.attention { + markers.push(Code::Char('*')); + } + if tokenizer.parse_state.constructs.autolink || tokenizer.parse_state.constructs.html_text { + markers.push(Code::Char('<')); + } + if tokenizer.parse_state.constructs.label_start_link { + markers.push(Code::Char('[')); + } + if tokenizer.parse_state.constructs.character_escape + || tokenizer.parse_state.constructs.hard_break_escape + { + markers.push(Code::Char('\\')); + } + if tokenizer.parse_state.constructs.label_end { + markers.push(Code::Char(']')); + } + if tokenizer.parse_state.constructs.attention { + markers.push(Code::Char('_')); + } + if tokenizer.parse_state.constructs.code_text { + markers.push(Code::Char('`')); + } + + before_marker(tokenizer, code, markers) +} + +/// Before text. +fn before_marker(tokenizer: &mut Tokenizer, code: Code, markers: Vec<Code>) -> StateFnResult { match code { Code::None => (State::Ok, None), _ => tokenizer.attempt_n( vec![ - // To do: build this vec based on whether they are enabled? Box::new(attention), Box::new(autolink), Box::new(character_escape), @@ -72,7 +89,10 @@ pub fn start(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { Box::new(label_start_link), Box::new(whitespace), ], - |ok| Box::new(if ok { start } else { before_data }), + |ok| { + let func = if ok { before_marker } else { before_data }; + Box::new(move |t, c| func(t, c, markers)) + }, )(tokenizer, code), } } @@ -82,6 +102,7 @@ pub fn start(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { /// ```markdown /// |qwe /// ``` -fn before_data(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { - tokenizer.go(|t, c| data(t, c, MARKERS.to_vec()), start)(tokenizer, code) +fn before_data(tokenizer: &mut Tokenizer, code: Code, markers: Vec<Code>) -> StateFnResult { + let copy = markers.clone(); + tokenizer.go(|t, c| data(t, c, copy), |t, c| before_marker(t, c, markers))(tokenizer, code) } |