aboutsummaryrefslogtreecommitdiffstats
path: root/src/construct/partial_data.rs
diff options
context:
space:
mode:
authorLibravatar Titus Wormer <tituswormer@gmail.com>2022-06-21 17:24:56 +0200
committerLibravatar Titus Wormer <tituswormer@gmail.com>2022-06-21 17:24:56 +0200
commit56ff5c73c7ec19b349e7d60d04ce1057c006d6ec (patch)
treeb4107ae0e0219f871a2f2764215ad979b2b0d75f /src/construct/partial_data.rs
parent7effd171218fff68f051671f1373cee467a8f921 (diff)
downloadmarkdown-rs-56ff5c73c7ec19b349e7d60d04ce1057c006d6ec.tar.gz
markdown-rs-56ff5c73c7ec19b349e7d60d04ce1057c006d6ec.tar.bz2
markdown-rs-56ff5c73c7ec19b349e7d60d04ce1057c006d6ec.zip
Make data a construct
Diffstat (limited to '')
-rw-r--r--src/construct/partial_data.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/construct/partial_data.rs b/src/construct/partial_data.rs
new file mode 100644
index 0000000..d83787a
--- /dev/null
+++ b/src/construct/partial_data.rs
@@ -0,0 +1,69 @@
+//! Data occurs in [text][] and [string][].
+//!
+//! It can include anything (including line endings), and stops at certain
+//! characters.
+//!
+//! [string]: crate::content::string
+//! [text]: crate::content::text
+
+// To do: pass token types in?
+
+use crate::tokenizer::{Code, State, StateFnResult, TokenType, Tokenizer};
+
+/// At the beginning of data.
+///
+/// ```markdown
+/// |&qwe
+/// ```
+pub fn start(tokenizer: &mut Tokenizer, code: Code, stop: Vec<Code>) -> StateFnResult {
+ if stop.contains(&code) {
+ tokenizer.enter(TokenType::Data);
+ tokenizer.consume(code);
+ (State::Fn(Box::new(|t, c| data(t, c, stop))), None)
+ } else {
+ at_break(tokenizer, code, stop)
+ }
+}
+
+/// Before something.
+///
+/// ```markdown
+/// |qwe| |&
+/// ```
+fn at_break(tokenizer: &mut Tokenizer, code: Code, stop: Vec<Code>) -> StateFnResult {
+ match code {
+ Code::None => (State::Ok, None),
+ Code::CarriageReturnLineFeed | Code::Char('\r' | '\n') => {
+ tokenizer.enter(TokenType::LineEnding);
+ tokenizer.consume(code);
+ tokenizer.exit(TokenType::LineEnding);
+ (State::Fn(Box::new(|t, c| at_break(t, c, stop))), None)
+ }
+ _ if stop.contains(&code) => (State::Ok, Some(vec![code])),
+ _ => {
+ tokenizer.enter(TokenType::Data);
+ data(tokenizer, code, stop)
+ }
+ }
+}
+
+/// In data.
+///
+/// ```markdown
+/// q|w|e
+/// ```
+fn data(tokenizer: &mut Tokenizer, code: Code, stop: Vec<Code>) -> StateFnResult {
+ let done = match code {
+ Code::None | Code::CarriageReturnLineFeed | Code::Char('\r' | '\n') => true,
+ _ if stop.contains(&code) => true,
+ _ => false,
+ };
+
+ if done {
+ tokenizer.exit(TokenType::Data);
+ at_break(tokenizer, code, stop)
+ } else {
+ tokenizer.consume(code);
+ (State::Fn(Box::new(|t, c| data(t, c, stop))), None)
+ }
+}