aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/content/document.rs4
-rw-r--r--src/subtokenize.rs2
-rw-r--r--src/tokenizer.rs58
3 files changed, 46 insertions, 18 deletions
diff --git a/src/content/document.rs b/src/content/document.rs
index d2c2426..63c2476 100644
--- a/src/content/document.rs
+++ b/src/content/document.rs
@@ -356,7 +356,7 @@ fn containers_after(
tokenizer.lazy = info.continued != info.stack.len();
tokenizer.interrupt = info.interrupt_before;
- tokenizer.define_skip(tokenizer.point.clone(), tokenizer.index);
+ tokenizer.define_skip_current();
let state = info.next;
info.next = Box::new(flow);
@@ -437,7 +437,7 @@ fn exit_containers(
// So, we’re at the end of a line, but we need to close the *previous* line.
if *phase != Phase::Eof {
- tokenizer.define_skip(tokenizer.point.clone(), tokenizer.index);
+ tokenizer.define_skip_current();
let mut current_events = tokenizer.events.drain(info.index..).collect::<Vec<_>>();
let next = info.next;
info.next = Box::new(flow); // This is weird but Rust needs a function there.
diff --git a/src/subtokenize.rs b/src/subtokenize.rs
index ad9a745..ce4f788 100644
--- a/src/subtokenize.rs
+++ b/src/subtokenize.rs
@@ -113,7 +113,7 @@ pub fn subtokenize(mut events: Vec<Event>, parse_state: &ParseState) -> (Vec<Eve
ends.push(span.end_index);
if enter.previous != None {
- tokenizer.define_skip(enter.point.clone(), enter.index);
+ tokenizer.define_skip(&enter.point, enter.index);
}
let func: Box<StateFn> = match result.0 {
diff --git a/src/tokenizer.rs b/src/tokenizer.rs
index 9b39e28..92a9e1a 100644
--- a/src/tokenizer.rs
+++ b/src/tokenizer.rs
@@ -13,7 +13,6 @@
use crate::parser::ParseState;
use crate::token::{Token, VOID_TOKENS};
-use std::collections::HashMap;
/// Embedded content type.
#[derive(Debug, Clone, Copy, PartialEq)]
@@ -175,7 +174,10 @@ struct InternalState {
/// A tokenizer itself.
#[allow(clippy::struct_excessive_bools)]
pub struct Tokenizer<'a> {
- column_start: HashMap<usize, (Point, usize)>,
+ /// Jump between line endings.
+ column_start: Vec<Option<(usize, usize, usize)>>,
+ // First line.
+ line_start: usize,
/// Track whether a character is expected to be consumed, and whether it’s
/// actually consumed
///
@@ -239,7 +241,9 @@ impl<'a> Tokenizer<'a> {
Tokenizer {
previous: Code::None,
current: Code::None,
- column_start: HashMap::new(),
+ // To do: reserve size when feeding?
+ column_start: vec![],
+ line_start: point.line,
index,
consumed: true,
drained: false,
@@ -285,24 +289,30 @@ impl<'a> Tokenizer<'a> {
}
/// Define a jump between two places.
- ///
- /// This defines how much columns are increased when consuming a line
- /// ending.
- pub fn define_skip(&mut self, point: Point, index: usize) {
- log::debug!("position: define skip: {:?}, {:?}", point, index);
- self.column_start.insert(point.line, (point, index));
- self.account_for_potential_skip();
+ pub fn define_skip(&mut self, point: &Point, index: usize) {
+ define_skip_current_impl(self, point.line, (point.column, point.offset, index));
+ }
+
+ /// Define the current place as a jump between two places.
+ pub fn define_skip_current(&mut self) {
+ define_skip_current_impl(
+ self,
+ self.point.line,
+ (self.point.column, self.point.offset, self.index),
+ );
}
/// Increment the current positional info if we’re right after a line
/// ending, which has a skip defined.
fn account_for_potential_skip(&mut self) {
- if self.point.column == 1 {
- match self.column_start.get(&self.point.line) {
+ let at = self.point.line - self.line_start;
+
+ if self.point.column == 1 && at < self.column_start.len() {
+ match &self.column_start[at] {
None => {}
- Some((point, index)) => {
- self.point.column = point.column;
- self.point.offset = point.offset;
+ Some((column, offset, index)) => {
+ self.point.column = *column;
+ self.point.offset = *offset;
self.index = *index;
}
};
@@ -756,6 +766,24 @@ fn flush_impl(
check_statefn_result((state, None))
}
+/// Define a jump between two places.
+///
+/// This defines how much columns, offsets, and the `index` are increased when
+/// consuming a line ending.
+fn define_skip_current_impl(tokenizer: &mut Tokenizer, line: usize, info: (usize, usize, usize)) {
+ log::debug!("position: define skip: {:?} -> ({:?})", line, info);
+ let at = line - tokenizer.line_start;
+
+ if at + 1 > tokenizer.column_start.len() {
+ tokenizer.column_start.resize(at, None);
+ tokenizer.column_start.push(Some(info));
+ } else {
+ tokenizer.column_start[at] = Some(info);
+ }
+
+ tokenizer.account_for_potential_skip();
+}
+
/// Check a [`StateFnResult`][], make sure its valid (that there are no bugs),
/// and clean a final eof passed back in `remainder`.
fn check_statefn_result(result: StateFnResult) -> StateFnResult {