use vize_l0::{Box, Vec};
mod lint_tag;
pub(crate) use lint_tag::{LintHeaderFact, LintTagFact};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TokenStatus {
Present,
Missing,
}
#[derive(Clone, Copy)]
pub struct Token<'a> {
pub leading: &'a str,
pub text: &'a str,
pub status: TokenStatus,
verbatim_opening: bool,
raw_interpolation: bool,
lint_tag: Option<LintTagFact>,
lint_header_literal: bool,
lint_table_context: bool,
lint_recovery_context: bool,
}
impl core::fmt::Debug for Token<'_> {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter
.debug_struct("Token")
.field("leading", &self.leading)
.field("text", &self.text)
.field("status", &self.status)
.finish()
}
}
impl<'a> Token<'a> {
pub fn present(leading: &'a str, text: &'a str) -> Self {
Self {
leading,
text,
status: TokenStatus::Present,
verbatim_opening: false,
raw_interpolation: false,
lint_tag: None,
lint_header_literal: false,
lint_table_context: false,
lint_recovery_context: false,
}
}
pub(crate) fn missing(leading: &'a str, at: &'a str) -> Self {
debug_assert!(at.is_empty());
Self {
leading,
text: at,
status: TokenStatus::Missing,
verbatim_opening: false,
raw_interpolation: false,
lint_tag: None,
lint_header_literal: false,
lint_table_context: false,
lint_recovery_context: false,
}
}
pub(crate) fn mark_verbatim_opening(&mut self, verbatim: bool) {
self.verbatim_opening = verbatim;
}
pub(crate) fn mark_raw_interpolation(&mut self) {
self.raw_interpolation = true;
}
pub(crate) fn mark_lint_tag(
&mut self,
fact: Option<LintTagFact>,
header_literal: bool,
table_context: bool,
recovery_context: bool,
) {
self.lint_tag = fact;
self.lint_header_literal = header_literal;
self.lint_table_context = table_context;
self.lint_recovery_context = recovery_context;
}
pub fn is_missing(&self) -> bool {
self.status == TokenStatus::Missing
}
}
#[derive(Debug)]
pub enum SurfaceChild<'a> {
Element(Box<'a, Element<'a>>),
Text(Token<'a>),
Interpolation(Box<'a, Interpolation<'a>>),
Comment(Token<'a>),
Cdata(Token<'a>),
ProcessingInstruction(Token<'a>),
Unexpected(Token<'a>),
}
#[derive(Debug)]
pub struct Interpolation<'a> {
pub open: Token<'a>,
pub content: Token<'a>,
pub close: Token<'a>,
}
impl Interpolation<'_> {
pub fn is_raw_html(&self) -> bool {
self.open.raw_interpolation
}
}
#[derive(Debug)]
pub struct Element<'a> {
pub open: OpenTag<'a>,
pub children: Vec<'a, SurfaceChild<'a>>,
pub close: ElementClose<'a>,
}
impl<'a> Element<'a> {
pub fn tag(&self) -> &'a str {
let text = self.open.lt_name.text;
text.get(1..).unwrap_or(text)
}
}
#[derive(Debug)]
pub struct OpenTag<'a> {
pub lt_name: Token<'a>,
pub attrs: Vec<'a, Attribute<'a>>,
pub slash: Option<Token<'a>>,
pub gt: Token<'a>,
}
impl OpenTag<'_> {
pub(crate) fn lint_tag(&self) -> Option<LintTagFact> {
self.lt_name.lint_tag
}
pub(crate) fn lint_header_is_literal(&self) -> bool {
self.lt_name.lint_header_literal
}
pub(crate) fn lint_in_table_context(&self) -> bool {
self.lt_name.lint_table_context
}
pub(crate) fn lint_in_recovery_context(&self) -> bool {
self.lt_name.lint_recovery_context
}
pub fn is_verbatim(&self) -> bool {
self.lt_name.verbatim_opening
}
}
#[derive(Debug)]
pub enum ElementClose<'a> {
Present(CloseTag<'a>),
Implicit,
Missing,
NotExpected,
}
#[derive(Debug)]
pub struct CloseTag<'a> {
pub lt_slash_name: Token<'a>,
pub gt: Token<'a>,
}
#[derive(Debug)]
pub struct Attribute<'a> {
pub name: Token<'a>,
pub eq: Option<Token<'a>>,
pub value: Option<AttrValue<'a>>,
}
#[derive(Debug)]
pub struct AttrValue<'a> {
pub open_quote: Option<Token<'a>>,
pub content: Token<'a>,
pub close_quote: Option<Token<'a>>,
}
impl<'a> AttrValue<'a> {
pub(crate) fn unquoted(content: Token<'a>) -> Self {
Self {
open_quote: None,
content,
close_quote: None,
}
}
}
#[derive(Debug)]
pub struct SurfaceTree<'a> {
pub source: &'a str,
pub children: Vec<'a, SurfaceChild<'a>>,
}
#[cfg(target_pointer_width = "64")]
const _: () = {
assert!(size_of::<Token<'_>>() == 40);
assert!(size_of::<Option<Token<'_>>>() == 40);
assert!(size_of::<Interpolation<'_>>() == 120);
assert!(size_of::<Attribute<'_>>() == 200);
assert!(size_of::<AttrValue<'_>>() == 120);
assert!(size_of::<OpenTag<'_>>() == 144);
assert!(size_of::<CloseTag<'_>>() == 80);
assert!(size_of::<ElementClose<'_>>() == 80);
assert!(size_of::<Element<'_>>() == 248);
assert!(size_of::<SurfaceChild<'_>>() == 48);
assert!(size_of::<SurfaceTree<'_>>() == 40);
};