aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/emitter.rs19
-rw-r--r--src/spans.rs57
-rw-r--r--src/tokenizer.rs1
3 files changed, 48 insertions, 29 deletions
diff --git a/src/emitter.rs b/src/emitter.rs
index e441eb7..18b2539 100644
--- a/src/emitter.rs
+++ b/src/emitter.rs
@@ -5,6 +5,7 @@ use std::collections::VecDeque;
use std::marker::PhantomData;
use std::mem;
+use crate::spans::Position;
use crate::spans::Span;
use crate::Error;
@@ -183,7 +184,7 @@ impl<R, S> Default for DefaultEmitter<R, S> {
}
}
-impl<R, S: Span<R>> DefaultEmitter<R, S> {
+impl<R, S: Span> DefaultEmitter<R, S> {
fn emit_token(&mut self, token: Token<S>) {
self.flush_current_characters();
self.emitted_tokens.push_front(token);
@@ -229,7 +230,7 @@ impl<R, S: Span<R>> DefaultEmitter<R, S> {
}
}
-impl<R, S: Span<R>> Emitter<R> for DefaultEmitter<R, S> {
+impl<R: Position<S::Offset>, S: Span> Emitter<R> for DefaultEmitter<R, S> {
type Token = Token<S>;
fn emit_eof(&mut self) {
@@ -237,7 +238,7 @@ impl<R, S: Span<R>> Emitter<R> for DefaultEmitter<R, S> {
}
fn emit_error(&mut self, error: Error, reader: &R) {
- self.push_error(error, S::from_reader(reader));
+ self.push_error(error, S::new(reader.position(), reader.position()));
}
fn pop_token(&mut self) -> Option<Self::Token> {
@@ -250,7 +251,7 @@ impl<R, S: Span<R>> Emitter<R> for DefaultEmitter<R, S> {
fn init_start_tag(&mut self, reader: &R) {
self.current_token = Some(Token::StartTag(StartTag {
- name_span: S::from_reader(reader),
+ name_span: S::new(reader.position(), reader.position()),
self_closing: false,
name: String::new(),
attributes: Default::default(),
@@ -258,7 +259,7 @@ impl<R, S: Span<R>> Emitter<R> for DefaultEmitter<R, S> {
}
fn init_end_tag(&mut self, reader: &R) {
self.current_token = Some(Token::EndTag(EndTag {
- name_span: S::from_reader(reader),
+ name_span: S::new(reader.position(), reader.position()),
name: String::new(),
}));
self.seen_attributes.clear();
@@ -367,15 +368,17 @@ impl<R, S: Span<R>> Emitter<R> for DefaultEmitter<R, S> {
self.current_attribute = Some((
String::new(),
Attribute {
- name_span: S::from_reader(reader),
+ name_span: S::new(reader.position(), reader.position()),
value: String::new(),
value_span: S::default(),
},
));
}
fn init_attribute_value(&mut self, reader: &R, quoted: bool) {
- self.current_attribute.as_mut().unwrap().1.value_span =
- S::from_reader_with_offset(reader, quoted as usize);
+ self.current_attribute.as_mut().unwrap().1.value_span = S::new(
+ reader.position() + quoted as usize,
+ reader.position() + quoted as usize,
+ );
}
fn push_attribute_name(&mut self, s: &str) {
diff --git a/src/spans.rs b/src/spans.rs
index 89595aa..14392cd 100644
--- a/src/spans.rs
+++ b/src/spans.rs
@@ -6,21 +6,29 @@
//! * one for `()` which acts as the no-op implementation for when you don't want to track spans
//! * one for [`Range<usize>`] for when you do want to track spans
//!
-//! To use the latter your reader however has to implement [`Position`].
+//! To use the latter your reader however has to implement [`Position<usize>`].
//! You can easily use any existing reader by wrapping it in the [`PosTrackingReader`] struct
-//! which implements the [`Position`] trait and takes care of tracking the current position.
+//! which implements the [`Position<usize>`] trait and takes care of tracking the current position.
-use std::ops::Range;
+use std::ops::{Add, Range};
use crate::reader::{IntoReader, Reader};
+pub struct NoopOffset;
+
/// A trait to be implemented by readers that track their own position.
-pub trait Position {
+pub trait Position<T> {
/// Returns the byte index of the current position.
- fn position(&self) -> usize;
+ fn position(&self) -> T;
+}
+
+impl<R: Reader> Position<NoopOffset> for R {
+ fn position(&self) -> NoopOffset {
+ NoopOffset
+ }
}
-/// Wraps a [`Reader`] so that it implements [`Position`].
+/// Wraps a [`Reader`] so that it implements [`Position<usize>`].
pub struct PosTrackingReader<R> {
/// The wrapped reader.
reader: R,
@@ -29,7 +37,7 @@ pub struct PosTrackingReader<R> {
}
impl<R> PosTrackingReader<R> {
- /// Wraps the given [`Reader`] so that it implements [`Position`] with the position starting from 0.
+ /// Wraps the given [`Reader`] so that it implements [`Position<usize>`] with the position starting from 0.
pub fn new<'a>(into_reader: impl IntoReader<'a, Reader = R>) -> Self {
Self {
reader: into_reader.into_reader(),
@@ -38,39 +46,46 @@ impl<R> PosTrackingReader<R> {
}
}
-impl<R> Position for PosTrackingReader<R> {
+impl<R> Position<usize> for PosTrackingReader<R> {
fn position(&self) -> usize {
self.position
}
}
/// A byte range in the source code.
-pub trait Span<R>: Default + Clone {
- /// Initializes a new span at the current position of the reader.
- fn from_reader(reader: &R) -> Self;
+pub trait Span: Default + Clone {
+ type Offset: Add<usize, Output = Self::Offset>;
- /// Initializes a new span at the current position of the reader with the given offset.
- fn from_reader_with_offset(reader: &R, offset: usize) -> Self;
+ /// Constructs a new span from the given byte offsets.
+ fn new(start: Self::Offset, end: Self::Offset) -> Self;
/// Extends the span by the length of the given string.
fn push_str(&mut self, str: &str);
}
-impl<R> Span<R> for () {
- fn from_reader(_reader: &R) -> Self {}
+impl Span for () {
+ type Offset = NoopOffset;
- fn from_reader_with_offset(_reader: &R, _offset: usize) -> Self {}
+ fn new(_start: Self::Offset, _end: Self::Offset) -> Self {
+ ()
+ }
fn push_str(&mut self, _str: &str) {}
}
-impl<P: Position> Span<P> for Range<usize> {
- fn from_reader(reader: &P) -> Self {
- reader.position() - 1..reader.position() - 1
+impl Add<usize> for NoopOffset {
+ type Output = Self;
+
+ fn add(self, _rhs: usize) -> NoopOffset {
+ self
}
+}
+
+impl Span for Range<usize> {
+ type Offset = usize;
- fn from_reader_with_offset(reader: &P, offset: usize) -> Self {
- reader.position() - 1 + offset..reader.position() - 1 + offset
+ fn new(start: Self::Offset, end: Self::Offset) -> Self {
+ start - 1..end - 1
}
fn push_str(&mut self, str: &str) {
diff --git a/src/tokenizer.rs b/src/tokenizer.rs
index 7768ee4..7b8b1ce 100644
--- a/src/tokenizer.rs
+++ b/src/tokenizer.rs
@@ -1,5 +1,6 @@
use crate::machine;
use crate::reader::{IntoReader, Reader};
+use crate::spans::Position;
use crate::utils::{
control_pat, noncharacter_pat, surrogate_pat, ControlToken, State as InternalState,
};