css_parse/traits/
to_cursors.rs

1use crate::CursorSink;
2use bumpalo::collections::Vec;
3
4/// This trait allows AST nodes to decompose themselves back into a set of (ordered) [Cursors][crate::Cursor].
5///
6/// This trait is useful to implement because downstream operations can use it to reconstruct source text from Nodes,
7/// including after mutating Nodes, such as transforming them (e.g. minification or formatting).
8///
9/// Nodes that implement this trait should call `s.append()` in the order that those [Cursors][crate::Cursor] were parsed,
10/// unless there's a good reason not to. Some good reasons not to:
11///
12///  - The specification supplies a specific grammar order.
13///  - Doing so would require creating many intermediary enums or structs.
14///
15pub trait ToCursors {
16	fn to_cursors(&self, s: &mut impl CursorSink);
17}
18
19impl<T> ToCursors for Option<T>
20where
21	T: ToCursors,
22{
23	fn to_cursors(&self, s: &mut impl CursorSink) {
24		if let Some(t) = self {
25			ToCursors::to_cursors(t, s);
26		}
27	}
28}
29
30impl<'a, T> ToCursors for Vec<'a, T>
31where
32	T: ToCursors,
33{
34	fn to_cursors(&self, s: &mut impl CursorSink) {
35		for item in self.iter() {
36			ToCursors::to_cursors(item, s);
37		}
38	}
39}
40
41macro_rules! impl_tuple {
42    ($($T:ident),*) => {
43        impl<$($T),*> ToCursors for ($($T),*)
44        where
45            $($T: ToCursors,)*
46        {
47            #[allow(non_snake_case)]
48            #[allow(unused)]
49            fn to_cursors(&self, s: &mut impl CursorSink) {
50                let ($($T),*) = self;
51                $($T.to_cursors(s);)*
52            }
53        }
54    };
55}
56
57impl_tuple!(A, B);
58impl_tuple!(A, B, C);
59impl_tuple!(A, B, C, D);
60impl_tuple!(A, B, C, D, E);
61impl_tuple!(A, B, C, D, E, F);
62impl_tuple!(A, B, C, D, E, F, G);
63impl_tuple!(A, B, C, D, E, F, G, H);
64impl_tuple!(A, B, C, D, E, F, G, H, I);
65impl_tuple!(A, B, C, D, E, F, G, H, I, J);
66impl_tuple!(A, B, C, D, E, F, G, H, I, J, K);
67impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);