1use std::ops::ControlFlow;
2
3use crate::{
4 Enum, Field, Function, Primitive, Schema, Struct, Type, TypeParameter, TypeReference,
5 Typespace, Variant,
6};
7
8pub trait Zero {
9 const ZERO: Self;
10}
11
12impl Zero for usize {
13 const ZERO: Self = 0;
14}
15
16impl Combine for usize {
17 fn combine(self, other: Self) -> Self {
18 self + other
19 }
20}
21
22impl Zero for () {
23 const ZERO: Self = ();
24}
25
26impl Combine for () {
27 fn combine(self, _other: Self) -> Self {}
28}
29
30pub trait Combine: Zero {
32 fn combine(self, other: Self) -> Self;
33}
34
35pub trait Visitor: Sized {
37 type Output: Combine;
39
40 fn visit_schema_inputs(&mut self, s: &mut Schema) -> ControlFlow<Self::Output, Self::Output> {
41 ControlFlow::Continue(
42 s.input_types.visit_mut(self)?.combine(
43 s.functions
44 .iter_mut()
45 .try_fold(Self::Output::ZERO, |acc, f| {
46 ControlFlow::Continue(acc.combine(self.visit_function_inputs(f)?))
47 })?,
48 ),
49 )
50 }
51
52 fn visit_schema_outputs(&mut self, s: &mut Schema) -> ControlFlow<Self::Output, Self::Output> {
53 ControlFlow::Continue(
54 s.output_types.visit_mut(self)?.combine(
55 s.functions
56 .iter_mut()
57 .try_fold(Self::Output::ZERO, |acc, f| {
58 ControlFlow::Continue(acc.combine(self.visit_function_outputs(f)?))
59 })?,
60 ),
61 )
62 }
63
64 fn visit_function_inputs(
65 &mut self,
66 f: &mut Function,
67 ) -> ControlFlow<Self::Output, Self::Output> {
68 let mut acc = Self::Output::ZERO;
69 if let Some(input_type) = &mut f.input_type {
70 acc = acc.combine(self.visit_type_ref(input_type)?);
71 }
72
73 if let Some(input_headers) = &mut f.input_headers {
74 acc = acc.combine(self.visit_type_ref(input_headers)?);
75 }
76
77 ControlFlow::Continue(acc)
78 }
79
80 fn visit_function_outputs(
81 &mut self,
82 f: &mut Function,
83 ) -> ControlFlow<Self::Output, Self::Output> {
84 let mut acc = Self::Output::ZERO;
85 match &mut f.output_type {
86 crate::OutputType::Complete { output_type } => {
87 if let Some(output_type) = output_type {
88 acc = acc.combine(self.visit_type_ref(output_type)?);
89 }
90 }
91 crate::OutputType::Stream { item_type } => {
92 acc = acc.combine(self.visit_type_ref(item_type)?);
93 }
94 }
95
96 if let Some(output_headers) = &mut f.error_type {
97 acc = acc.combine(self.visit_type_ref(output_headers)?);
98 }
99
100 ControlFlow::Continue(acc)
101 }
102
103 fn visit_type(&mut self, t: &mut Type) -> ControlFlow<Self::Output, Self::Output> {
104 t.visit_mut(self)
105 }
106
107 fn visit_enum(&mut self, e: &mut Enum) -> ControlFlow<Self::Output, Self::Output> {
108 e.visit_mut(self)
109 }
110
111 fn visit_variant(&mut self, v: &mut Variant) -> ControlFlow<Self::Output, Self::Output> {
112 v.visit_mut(self)
113 }
114
115 fn visit_struct(&mut self, s: &mut Struct) -> ControlFlow<Self::Output, Self::Output> {
116 s.visit_mut(self)
117 }
118
119 fn visit_primitive(&mut self, p: &mut Primitive) -> ControlFlow<Self::Output, Self::Output> {
120 p.visit_mut(self)
121 }
122
123 fn visit_type_parameter(
124 &mut self,
125 _p: &mut TypeParameter,
126 ) -> ControlFlow<Self::Output, Self::Output> {
127 ControlFlow::Continue(Self::Output::ZERO)
128 }
129
130 fn visit_field(&mut self, f: &mut Field) -> ControlFlow<Self::Output, Self::Output> {
131 f.visit_mut(self)
132 }
133
134 fn visit_type_ref(
135 &mut self,
136 type_ref: &mut TypeReference,
137 ) -> ControlFlow<Self::Output, Self::Output> {
138 type_ref.visit_mut(self)
139 }
140
141 fn visit_top_level_name(
143 &mut self,
144 _name: &mut String,
145 ) -> ControlFlow<Self::Output, Self::Output> {
146 ControlFlow::Continue(Self::Output::ZERO)
147 }
148}
149
150pub trait VisitMut {
151 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output>;
152}
153
154impl VisitMut for Typespace {
155 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
156 self.invalidate_types_map();
157 self.types.iter_mut().try_fold(V::Output::ZERO, |acc, t| {
158 ControlFlow::Continue(acc.combine(visitor.visit_type(t)?))
159 })
160 }
161}
162
163impl VisitMut for Type {
164 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
165 match self {
166 Type::Struct(s) => visitor.visit_struct(s),
167 Type::Enum(e) => visitor.visit_enum(e),
168 Type::Primitive(p) => visitor.visit_primitive(p),
169 }
170 }
171}
172
173impl VisitMut for Struct {
174 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
175 let ps = self
176 .parameters
177 .iter_mut()
178 .try_fold(V::Output::ZERO, |acc, p| {
179 ControlFlow::Continue(acc.combine(visitor.visit_type_parameter(p)?))
180 })?;
181
182 let fs = self.fields.iter_mut().try_fold(V::Output::ZERO, |acc, f| {
183 ControlFlow::Continue(acc.combine(visitor.visit_field(f)?))
184 })?;
185
186 ControlFlow::Continue(
187 ps.combine(fs)
188 .combine(visitor.visit_top_level_name(&mut self.name)?),
189 )
190 }
191}
192
193impl VisitMut for Enum {
194 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
195 let ps = self
196 .parameters
197 .iter_mut()
198 .try_fold(V::Output::ZERO, |acc, p| {
199 ControlFlow::Continue(acc.combine(visitor.visit_type_parameter(p)?))
200 })?;
201
202 let vs = self
203 .variants
204 .iter_mut()
205 .try_fold(V::Output::ZERO, |acc, v| {
206 ControlFlow::Continue(acc.combine(visitor.visit_variant(v)?))
207 })?;
208
209 ControlFlow::Continue(
210 ps.combine(vs)
211 .combine(visitor.visit_top_level_name(&mut self.name)?),
212 )
213 }
214}
215
216impl VisitMut for Variant {
217 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
218 self.fields.iter_mut().try_fold(V::Output::ZERO, |acc, f| {
219 ControlFlow::Continue(acc.combine(visitor.visit_field(f)?))
220 })
221 }
222}
223
224impl VisitMut for Primitive {
225 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
226 ControlFlow::Continue(
227 self.parameters
228 .iter_mut()
229 .try_fold(V::Output::ZERO, |acc, p| {
230 ControlFlow::Continue(acc.combine(visitor.visit_type_parameter(p)?))
231 })?
232 .combine(visitor.visit_top_level_name(&mut self.name)?),
233 )
234 }
235}
236
237impl VisitMut for Field {
238 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
239 visitor.visit_type_ref(&mut self.type_ref)
240 }
241}
242
243impl VisitMut for TypeReference {
244 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
245 ControlFlow::Continue(
246 self.arguments
247 .iter_mut()
248 .try_fold(V::Output::ZERO, |acc, a| {
249 ControlFlow::Continue(acc.combine(visitor.visit_type_ref(a)?))
250 })?
251 .combine(visitor.visit_top_level_name(&mut self.name)?),
252 )
253 }
254}