Skip to main content

css_parse/syntax/
declaration_or_bad.rs

1use crate::{
2	BadDeclaration, CursorSink, Declaration, DeclarationValue, NodeMetadata, NodeWithMetadata, SemanticEq, Span,
3	ToCursors, ToSpan,
4};
5use csskit_proc_macro::node;
6
7/// Either a valid declaration or a bad declaration consumed for error recovery.
8///
9/// Per the CSS spec, when parsing fails for both a declaration and a rule,
10/// we consume the remnants as a bad declaration to maintain error recovery.
11#[node]
12#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
14pub enum DeclarationOrBad<'a, D, M>
15where
16	D: DeclarationValue<'a, M>,
17	M: NodeMetadata,
18{
19	Declaration(Declaration<'a, D, M>),
20	Bad(BadDeclaration<'a>),
21}
22
23impl<'a, D, M> ToCursors for DeclarationOrBad<'a, D, M>
24where
25	D: DeclarationValue<'a, M> + ToCursors,
26	M: NodeMetadata,
27{
28	fn to_cursors(&self, s: &mut impl CursorSink) {
29		match self {
30			Self::Declaration(d) => d.to_cursors(s),
31			Self::Bad(b) => b.to_cursors(s),
32		}
33	}
34}
35
36impl<'a, D, M> ToSpan for DeclarationOrBad<'a, D, M>
37where
38	D: DeclarationValue<'a, M> + ToSpan,
39	M: NodeMetadata,
40{
41	fn to_span(&self) -> Span {
42		match self {
43			Self::Declaration(d) => d.to_span(),
44			Self::Bad(b) => b.to_span(),
45		}
46	}
47}
48
49impl<'a, D, M> SemanticEq for DeclarationOrBad<'a, D, M>
50where
51	D: DeclarationValue<'a, M>,
52	M: NodeMetadata,
53{
54	fn semantic_eq(&self, other: &Self) -> bool {
55		match (self, other) {
56			(Self::Declaration(a), Self::Declaration(b)) => a.semantic_eq(b),
57			(Self::Bad(a), Self::Bad(b)) => a.semantic_eq(b),
58			_ => false,
59		}
60	}
61}
62
63impl<'a, D, M> NodeWithMetadata<M> for DeclarationOrBad<'a, D, M>
64where
65	D: DeclarationValue<'a, M>,
66	M: NodeMetadata,
67{
68	fn metadata(&self) -> M {
69		match self {
70			Self::Declaration(d) => d.metadata(),
71			Self::Bad(b) => b.metadata(),
72		}
73	}
74}