1use std::{
4 num::NonZeroUsize,
5 ops::{Index, Range},
6};
7
8use crate::let_else::assume;
9use crate::token::AttributeTraceIdx;
10
11#[allow(missing_docs)]
15#[derive(Eq, PartialEq, Debug)]
16pub enum Trace {
17 Char(Range<usize>),
18 StartTag(StartTagTrace),
19 EndTag(EndTagTrace),
20 Comment(CommentTrace),
21 Doctype(DoctypeTrace),
22 EndOfFile(usize),
23}
24
25#[derive(Eq, PartialEq, Debug)]
29pub struct StartTagTrace {
30 pub span: Range<usize>,
32
33 pub name_span: Range<usize>,
35
36 pub attribute_traces: AttributeTraceList,
38}
39
40#[derive(Eq, PartialEq, Debug)]
44pub struct EndTagTrace {
45 pub span: Range<usize>,
47
48 pub name_span: Range<usize>,
50}
51
52#[derive(Eq, PartialEq, Debug)]
56pub struct CommentTrace {
57 pub data_span: Range<usize>,
59}
60
61#[derive(Eq, PartialEq, Debug)]
65pub struct DoctypeTrace {
66 pub(crate) span: Range<usize>,
67 name_span: Option<Range<std::num::NonZeroUsize>>,
69 public_id_span: Option<Range<std::num::NonZeroUsize>>,
70 system_id_span: Option<Range<std::num::NonZeroUsize>>,
71}
72
73impl DoctypeTrace {
74 pub fn span(&self) -> Range<usize> {
76 self.span.clone()
77 }
78
79 pub fn name_span(&self) -> Option<Range<usize>> {
81 self.name_span
82 .as_ref()
83 .map(|range| range.start.get()..range.end.get())
84 }
85
86 pub fn public_id_span(&self) -> Option<Range<usize>> {
88 self.public_id_span
89 .as_ref()
90 .map(|range| range.start.get()..range.end.get())
91 }
92
93 pub fn system_id_span(&self) -> Option<Range<usize>> {
95 self.system_id_span
96 .as_ref()
97 .map(|range| range.start.get()..range.end.get())
98 }
99}
100
101impl DoctypeTrace {
108 #[inline]
109 pub(crate) fn new(span_start: usize) -> Self {
110 Self {
111 span: span_start..0,
112 name_span: None,
113 public_id_span: None,
114 system_id_span: None,
115 }
116 }
117
118 #[inline]
119 pub(crate) fn set_name_start(&mut self, start: usize) {
120 let start = NonZeroUsize::new(start).expect("expected offset to be non-zero");
121 self.name_span = Some(start..start);
122 }
123
124 #[inline]
125 pub(crate) fn set_public_id_start(&mut self, start: usize) {
126 let start = NonZeroUsize::new(start).expect("expected offset to be non-zero");
127 self.public_id_span = Some(start..start);
128 }
129
130 #[inline]
131 pub(crate) fn set_system_id_start(&mut self, start: usize) {
132 let start = NonZeroUsize::new(start).expect("expected offset to be non-zero");
133 self.system_id_span = Some(start..start);
134 }
135
136 #[inline]
137 pub(crate) fn set_name_end(&mut self, end: usize) {
138 assume!(Some(span), &mut self.name_span);
139 span.end = NonZeroUsize::new(end).expect("expected offset to be non-zero");
140 }
141
142 #[inline]
143 pub(crate) fn set_public_id_end(&mut self, end: usize) {
144 assume!(Some(span), &mut self.public_id_span);
145 span.end = NonZeroUsize::new(end).expect("expected offset to be non-zero");
146 }
147
148 #[inline]
149 pub(crate) fn set_system_id_end(&mut self, end: usize) {
150 assume!(Some(span), &mut self.system_id_span);
151 span.end = NonZeroUsize::new(end).expect("expected offset to be non-zero");
152 }
153}
154
155#[derive(Clone, Copy, PartialEq, Eq, Debug)]
157pub enum AttrValueSyntax {
158 Unquoted,
160 SingleQuoted,
162 DoubleQuoted,
164}
165
166#[derive(Eq, PartialEq, Debug)]
168pub struct AttributeTrace {
169 pub(crate) value_syntax: Option<AttrValueSyntax>,
170 pub(crate) name_span: Range<usize>,
171 pub(crate) value_span: Range<usize>,
174}
175
176impl AttributeTrace {
177 pub(crate) fn new() -> Self {
180 Self {
181 value_syntax: None,
182 name_span: Default::default(),
183 value_span: Default::default(),
184 }
185 }
186
187 pub fn name_span(&self) -> Range<usize> {
189 self.name_span.clone()
190 }
191
192 pub fn value_span(&self) -> Option<Range<usize>> {
196 if self.value_syntax.is_none() {
197 return None;
198 }
199 Some(self.value_span.clone())
200 }
201
202 pub fn value_syntax(&self) -> Option<AttrValueSyntax> {
206 self.value_syntax
207 }
208}
209
210#[derive(Eq, PartialEq, Debug)]
212pub struct AttributeTraceList {
213 traces: Vec<AttributeTrace>,
216}
217
218impl Index<AttributeTraceIdx> for AttributeTraceList {
219 type Output = AttributeTrace;
220
221 fn index(&self, index: AttributeTraceIdx) -> &Self::Output {
222 &self.traces[index.0.get() - 1]
223 }
224}
225
226impl AttributeTraceList {
227 pub(crate) fn new() -> Self {
228 Self {
229 traces: Default::default(),
230 }
231 }
232
233 pub(crate) fn insert(&mut self, trace: AttributeTrace) -> AttributeTraceIdx {
234 self.traces.push(trace);
235 let len = self.traces.len();
236 AttributeTraceIdx(
237 unsafe { std::num::NonZeroUsize::new_unchecked(len) },
239 )
240 }
241}