aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Titus Wormer <tituswormer@gmail.com>2022-07-18 17:24:32 +0200
committerLibravatar Titus Wormer <tituswormer@gmail.com>2022-07-18 17:24:32 +0200
commitd2a7c1fb0344971ac537e15d1a4b00fe18ff8c43 (patch)
tree1a9e8f889a3a0a63d0fde7fc1baf8eb3a8e6ba61 /src
parent7186ce91784a647b3015e04b55a95b109deceeb3 (diff)
downloadmarkdown-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 'src')
-rw-r--r--src/content/string.rs47
-rw-r--r--src/content/text.rs75
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
-/// |&amp;
-/// |\&
-/// |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
-/// |&amp;
-/// |\&
-/// |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)
}