css_parse/syntax/
declaration_or_bad.rs

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