use std::{
num::NonZeroUsize,
ops::{Index, Range},
};
use crate::let_else::assume;
use crate::token::AttributeTraceIdx;
#[allow(missing_docs)]
#[derive(Eq, PartialEq, Debug)]
pub enum Trace {
Char(Range<usize>),
StartTag(StartTagTrace),
EndTag(EndTagTrace),
Comment(CommentTrace),
Doctype(DoctypeTrace),
EndOfFile(usize),
}
#[derive(Eq, PartialEq, Debug)]
pub struct StartTagTrace {
pub span: Range<usize>,
pub name_span: Range<usize>,
pub attribute_traces: AttributeTraceList,
}
#[derive(Eq, PartialEq, Debug)]
pub struct EndTagTrace {
pub span: Range<usize>,
pub name_span: Range<usize>,
}
#[derive(Eq, PartialEq, Debug)]
pub struct CommentTrace {
pub data_span: Range<usize>,
}
#[derive(Eq, PartialEq, Debug)]
pub struct DoctypeTrace {
pub(crate) span: Range<usize>,
name_span: Option<Range<std::num::NonZeroUsize>>,
public_id_span: Option<Range<std::num::NonZeroUsize>>,
system_id_span: Option<Range<std::num::NonZeroUsize>>,
}
impl DoctypeTrace {
pub fn span(&self) -> Range<usize> {
self.span.clone()
}
pub fn name_span(&self) -> Option<Range<usize>> {
self.name_span
.as_ref()
.map(|range| range.start.get()..range.end.get())
}
pub fn public_id_span(&self) -> Option<Range<usize>> {
self.public_id_span
.as_ref()
.map(|range| range.start.get()..range.end.get())
}
pub fn system_id_span(&self) -> Option<Range<usize>> {
self.system_id_span
.as_ref()
.map(|range| range.start.get()..range.end.get())
}
}
impl DoctypeTrace {
#[inline]
pub(crate) fn new(span_start: usize) -> Self {
Self {
span: span_start..0,
name_span: None,
public_id_span: None,
system_id_span: None,
}
}
#[inline]
pub(crate) fn set_name_start(&mut self, start: usize) {
let start = NonZeroUsize::new(start).expect("expected offset to be non-zero");
self.name_span = Some(start..start);
}
#[inline]
pub(crate) fn set_public_id_start(&mut self, start: usize) {
let start = NonZeroUsize::new(start).expect("expected offset to be non-zero");
self.public_id_span = Some(start..start);
}
#[inline]
pub(crate) fn set_system_id_start(&mut self, start: usize) {
let start = NonZeroUsize::new(start).expect("expected offset to be non-zero");
self.system_id_span = Some(start..start);
}
#[inline]
pub(crate) fn set_name_end(&mut self, end: usize) {
assume!(Some(span), &mut self.name_span);
span.end = NonZeroUsize::new(end).expect("expected offset to be non-zero");
}
#[inline]
pub(crate) fn set_public_id_end(&mut self, end: usize) {
assume!(Some(span), &mut self.public_id_span);
span.end = NonZeroUsize::new(end).expect("expected offset to be non-zero");
}
#[inline]
pub(crate) fn set_system_id_end(&mut self, end: usize) {
assume!(Some(span), &mut self.system_id_span);
span.end = NonZeroUsize::new(end).expect("expected offset to be non-zero");
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum AttrValueSyntax {
Unquoted,
SingleQuoted,
DoubleQuoted,
}
#[derive(Eq, PartialEq, Debug)]
pub struct AttributeTrace {
pub(crate) value_syntax: Option<AttrValueSyntax>,
pub(crate) name_span: Range<usize>,
pub(crate) value_span: Range<usize>,
}
impl AttributeTrace {
pub(crate) fn new() -> Self {
Self {
value_syntax: None,
name_span: Default::default(),
value_span: Default::default(),
}
}
pub fn name_span(&self) -> Range<usize> {
self.name_span.clone()
}
pub fn value_span(&self) -> Option<Range<usize>> {
if self.value_syntax.is_none() {
return None;
}
Some(self.value_span.clone())
}
pub fn value_syntax(&self) -> Option<AttrValueSyntax> {
self.value_syntax
}
}
#[derive(Eq, PartialEq, Debug)]
pub struct AttributeTraceList {
traces: Vec<AttributeTrace>,
}
impl Index<AttributeTraceIdx> for AttributeTraceList {
type Output = AttributeTrace;
fn index(&self, index: AttributeTraceIdx) -> &Self::Output {
&self.traces[index.0.get() - 1]
}
}
impl AttributeTraceList {
pub(crate) fn new() -> Self {
Self {
traces: Default::default(),
}
}
pub(crate) fn insert(&mut self, trace: AttributeTrace) -> AttributeTraceIdx {
self.traces.push(trace);
let len = self.traces.len();
AttributeTraceIdx(
unsafe { std::num::NonZeroUsize::new_unchecked(len) },
)
}
}