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 if let Some(output_type) = &mut f.output_type {
86 acc = acc.combine(self.visit_type_ref(output_type)?);
87 }
88
89 if let Some(output_headers) = &mut f.error_type {
90 acc = acc.combine(self.visit_type_ref(output_headers)?);
91 }
92
93 ControlFlow::Continue(acc)
94 }
95
96 fn visit_type(&mut self, t: &mut Type) -> ControlFlow<Self::Output, Self::Output> {
97 t.visit_mut(self)
98 }
99
100 fn visit_enum(&mut self, e: &mut Enum) -> ControlFlow<Self::Output, Self::Output> {
101 e.visit_mut(self)
102 }
103
104 fn visit_variant(&mut self, v: &mut Variant) -> ControlFlow<Self::Output, Self::Output> {
105 v.visit_mut(self)
106 }
107
108 fn visit_struct(&mut self, s: &mut Struct) -> ControlFlow<Self::Output, Self::Output> {
109 s.visit_mut(self)
110 }
111
112 fn visit_primitive(&mut self, p: &mut Primitive) -> ControlFlow<Self::Output, Self::Output> {
113 p.visit_mut(self)
114 }
115
116 fn visit_type_parameter(
117 &mut self,
118 _p: &mut TypeParameter,
119 ) -> ControlFlow<Self::Output, Self::Output> {
120 ControlFlow::Continue(Self::Output::ZERO)
121 }
122
123 fn visit_field(&mut self, f: &mut Field) -> ControlFlow<Self::Output, Self::Output> {
124 f.visit_mut(self)
125 }
126
127 fn visit_type_ref(
128 &mut self,
129 type_ref: &mut TypeReference,
130 ) -> ControlFlow<Self::Output, Self::Output> {
131 type_ref.visit_mut(self)
132 }
133
134 fn visit_top_level_name(
136 &mut self,
137 _name: &mut String,
138 ) -> ControlFlow<Self::Output, Self::Output> {
139 ControlFlow::Continue(Self::Output::ZERO)
140 }
141}
142
143pub trait VisitMut {
144 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output>;
145}
146
147impl VisitMut for Typespace {
148 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
149 self.invalidate_types_map();
150 self.types.iter_mut().try_fold(V::Output::ZERO, |acc, t| {
151 ControlFlow::Continue(acc.combine(visitor.visit_type(t)?))
152 })
153 }
154}
155
156impl VisitMut for Type {
157 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
158 match self {
159 Type::Struct(s) => visitor.visit_struct(s),
160 Type::Enum(e) => visitor.visit_enum(e),
161 Type::Primitive(p) => visitor.visit_primitive(p),
162 }
163 }
164}
165
166impl VisitMut for Struct {
167 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
168 let ps = self
169 .parameters
170 .iter_mut()
171 .try_fold(V::Output::ZERO, |acc, p| {
172 ControlFlow::Continue(acc.combine(visitor.visit_type_parameter(p)?))
173 })?;
174
175 let fs = self.fields.iter_mut().try_fold(V::Output::ZERO, |acc, f| {
176 ControlFlow::Continue(acc.combine(visitor.visit_field(f)?))
177 })?;
178
179 ControlFlow::Continue(
180 ps.combine(fs)
181 .combine(visitor.visit_top_level_name(&mut self.name)?),
182 )
183 }
184}
185
186impl VisitMut for Enum {
187 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
188 let ps = self
189 .parameters
190 .iter_mut()
191 .try_fold(V::Output::ZERO, |acc, p| {
192 ControlFlow::Continue(acc.combine(visitor.visit_type_parameter(p)?))
193 })?;
194
195 let vs = self
196 .variants
197 .iter_mut()
198 .try_fold(V::Output::ZERO, |acc, v| {
199 ControlFlow::Continue(acc.combine(visitor.visit_variant(v)?))
200 })?;
201
202 ControlFlow::Continue(
203 ps.combine(vs)
204 .combine(visitor.visit_top_level_name(&mut self.name)?),
205 )
206 }
207}
208
209impl VisitMut for Variant {
210 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
211 self.fields.iter_mut().try_fold(V::Output::ZERO, |acc, f| {
212 ControlFlow::Continue(acc.combine(visitor.visit_field(f)?))
213 })
214 }
215}
216
217impl VisitMut for Primitive {
218 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
219 ControlFlow::Continue(
220 self.parameters
221 .iter_mut()
222 .try_fold(V::Output::ZERO, |acc, p| {
223 ControlFlow::Continue(acc.combine(visitor.visit_type_parameter(p)?))
224 })?
225 .combine(visitor.visit_top_level_name(&mut self.name)?),
226 )
227 }
228}
229
230impl VisitMut for Field {
231 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
232 visitor.visit_type_ref(&mut self.type_ref)
233 }
234}
235
236impl VisitMut for TypeReference {
237 fn visit_mut<V: Visitor>(&mut self, visitor: &mut V) -> ControlFlow<V::Output, V::Output> {
238 ControlFlow::Continue(
239 self.arguments
240 .iter_mut()
241 .try_fold(V::Output::ZERO, |acc, a| {
242 ControlFlow::Continue(acc.combine(visitor.visit_type_ref(a)?))
243 })?
244 .combine(visitor.visit_top_level_name(&mut self.name)?),
245 )
246 }
247}