1use crate::Block;
11use alloc::string::{String, ToString};
12
13#[derive(Debug)]
14pub struct View<'ast, S, F> {
15 parent: &'ast Block<S>,
16 mapping: F,
17}
18
19impl<S, F: Clone> Clone for View<'_, S, F> {
20 #[inline]
21 fn clone(&self) -> Self {
22 Self {
23 parent: self.parent,
24 mapping: self.mapping.clone(),
25 }
26 }
27}
28
29impl<S, F: Copy> Copy for View<'_, S, F> {}
30
31impl<'ast, S, F> View<'ast, S, F> {
32 #[inline]
33 pub const fn new(parent: &'ast Block<S>, mapping: F) -> Self {
34 Self { parent, mapping }
35 }
36}
37
38#[derive(Clone, Copy)]
39pub struct MapViewFn<F1, F2> {
40 f1: F1,
41 f2: F2,
42}
43
44pub trait ViewFn<S> {
46 type Output: Sized;
47
48 fn view(&self, node: S) -> Self::Output;
49}
50
51impl<S> ViewFn<S> for () {
52 type Output = S;
53
54 #[inline]
55 fn view(&self, node: S) -> S {
56 node
57 }
58}
59
60impl<S, F, O> ViewFn<S> for F
61where
62 F: Fn(S) -> O,
63{
64 type Output = O;
65
66 #[inline]
67 fn view(&self, node: S) -> O {
68 (self)(node)
69 }
70}
71
72impl<S, F: ViewFn<S>> ViewFn<S> for alloc::rc::Rc<F> {
73 type Output = F::Output;
74 #[inline]
75 fn view(&self, node: S) -> F::Output {
76 (&**self).view(node)
77 }
78}
79impl<S, F: ViewFn<S>> ViewFn<S> for alloc::sync::Arc<F> {
80 type Output = F::Output;
81 #[inline]
82 fn view(&self, node: S) -> F::Output {
83 (&**self).view(node)
84 }
85}
86
87impl<S, F1, F2, O> ViewFn<S> for MapViewFn<F1, F2>
88where
89 F1: ViewFn<S>,
90 F2: Fn(F1::Output) -> O,
91{
92 type Output = O;
93
94 #[inline]
95 fn view(&self, node: S) -> O {
96 (self.f2)(self.f1.view(node))
97 }
98}
99
100impl<'ast, S: 'ast, F> View<'ast, S, F>
101where
102 F: ViewFn<&'ast S>,
103{
104 #[inline]
105 pub fn head(&self) -> F::Output {
106 self.mapping.view(&self.parent.head)
107 }
108
109 #[inline]
110 pub fn map<F2, O2>(self, f2: F2) -> View<'ast, S, MapViewFn<F, F2>>
111 where
112 F2: Fn(F::Output) -> O2,
113 {
114 let View { parent, mapping } = self;
115 View {
116 parent,
117 mapping: MapViewFn { f1: mapping, f2 },
118 }
119 }
120}
121
122impl<'ast, S: 'ast, F> View<'ast, S, F>
123where
124 F: Clone + ViewFn<&'ast S>,
125{
126 #[inline]
127 pub fn subs(
128 &self,
129 ) -> core::iter::Map<
130 core::slice::Iter<'ast, Block<S>>,
131 impl Fn(&'ast Block<S>) -> View<'ast, S, F>,
132 > {
133 let mapping = self.mapping.clone();
134 let imapf = move |parent: &'ast Block<S>| View {
135 parent,
136 mapping: mapping.clone(),
137 };
138 self.parent.subs.iter().map(imapf)
139 }
140}
141
142impl<'ast, S: 'ast, F> View<'ast, S, F>
143where
144 F: Clone + ViewFn<&'ast S>,
145 F::Output: ToString,
146{
147 pub(crate) fn append_to_string(
148 &self,
149 ret: &mut String,
150 single_indent: &str,
151 upper_indent_factor: u32,
152 ) {
153 for _ in 0..upper_indent_factor {
154 ret.push_str(single_indent);
155 }
156 *ret += &self.head().to_string();
157 ret.push('\n');
158 let next_luif = upper_indent_factor + 1;
159 for i in self.subs() {
160 i.append_to_string(ret, single_indent, next_luif);
161 }
162 }
163}