css_parse/traits/
to_cursors.rs

1use crate::{Cursor, 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 ToCursors for Cursor {
20	fn to_cursors(&self, s: &mut impl CursorSink) {
21		s.append(*self);
22	}
23}
24
25impl<T> ToCursors for Option<T>
26where
27	T: ToCursors,
28{
29	fn to_cursors(&self, s: &mut impl CursorSink) {
30		if let Some(t) = self {
31			ToCursors::to_cursors(t, s);
32		}
33	}
34}
35
36impl<'a, T> ToCursors for Vec<'a, T>
37where
38	T: ToCursors,
39{
40	fn to_cursors(&self, s: &mut impl CursorSink) {
41		for item in self.iter() {
42			ToCursors::to_cursors(item, s);
43		}
44	}
45}
46
47macro_rules! impl_tuple {
48    ($($T:ident),*) => {
49        impl<$($T),*> ToCursors for ($($T),*)
50        where
51            $($T: ToCursors,)*
52        {
53            #[allow(non_snake_case)]
54            #[allow(unused)]
55            fn to_cursors(&self, s: &mut impl CursorSink) {
56                let ($($T),*) = self;
57                $($T.to_cursors(s);)*
58            }
59        }
60    };
61}
62
63impl_tuple!(A, B);
64impl_tuple!(A, B, C);
65impl_tuple!(A, B, C, D);
66impl_tuple!(A, B, C, D, E);
67impl_tuple!(A, B, C, D, E, F);
68impl_tuple!(A, B, C, D, E, F, G);
69impl_tuple!(A, B, C, D, E, F, G, H);
70impl_tuple!(A, B, C, D, E, F, G, H, I);
71impl_tuple!(A, B, C, D, E, F, G, H, I, J);
72impl_tuple!(A, B, C, D, E, F, G, H, I, J, K);
73impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);