1use super::Shape;
2use super::ShapeCase;
3use crate::case_enum::Error;
4use crate::location::Location;
5use crate::name::Name;
6use crate::name::NameCase;
7
8impl Shape {
9 #[must_use]
12 pub fn field(&self, field_name: &str, locations: impl IntoIterator<Item = Location>) -> Shape {
13 let locations = locations.into_iter().collect::<Vec<_>>();
14
15 let child_shape = match self.case() {
16 ShapeCase::Object { fields, rest } => {
17 if let Some(shape) = fields.get(field_name) {
18 shape.clone().with_locations(locations.iter())
19 } else {
20 Shape::one(
23 [rest.clone().with_locations(locations.iter()), Shape::none()],
24 locations.clone(),
25 )
26 }
27 }
28
29 ShapeCase::Array { prefix, tail } => {
30 let new_items = prefix
33 .iter()
34 .map(|shape| shape.field(field_name, locations.clone()))
35 .collect::<Vec<_>>();
36
37 let new_rest = tail.field(field_name, locations.clone());
38
39 if new_rest.is_none() && new_items.iter().all(Shape::is_none) {
43 Shape::none()
44 } else {
45 Shape::array(new_items, new_rest, locations.clone())
46 }
47 }
48
49 ShapeCase::One(shapes) => Shape::one(
50 shapes
51 .iter()
52 .map(|shape| shape.field(field_name, locations.clone())),
53 locations.clone(),
54 ),
55
56 ShapeCase::All(shapes) => Shape::all(
57 shapes
58 .iter()
59 .map(|shape| shape.field(field_name, locations.clone())),
60 locations.clone(),
61 ),
62
63 ShapeCase::Name(name, weak) => {
64 if let Some(named_shape) = weak.upgrade(name) {
65 named_shape.field(field_name, locations.clone())
66 } else {
67 Shape::new(
68 ShapeCase::Name(name.field(field_name, locations.clone()), weak.clone()),
69 locations.clone(),
70 )
71 }
72 }
73
74 ShapeCase::Error(Error { partial, .. }) => {
75 partial.as_ref().map_or(Shape::none(), |shape| {
76 shape.field(field_name, locations.clone())
77 })
78 }
79
80 ShapeCase::Unknown => self.clone().with_locations(locations.iter()),
81
82 _ => Shape::none(),
83 };
84
85 self.propagate_names_to_child(child_shape.with_locations(locations.iter()), |name| {
86 name.field(field_name, locations.clone())
87 })
88 }
89
90 fn propagate_names_to_child(
91 &self,
92 child_shape: Shape,
93 name_mapper: impl Fn(&Name) -> Name,
94 ) -> Shape {
95 let mapped_names = self.names().map(name_mapper);
96 let mut named = child_shape;
97 for name in mapped_names {
98 named = named.with_name(&name);
99 }
100 named
101 }
102
103 #[must_use]
106 pub fn any_field(&self, locations: impl IntoIterator<Item = Location>) -> Shape {
107 let locations = locations.into_iter().collect::<Vec<_>>();
108
109 let child_shape = match self.case() {
110 ShapeCase::Object { fields, rest } => {
111 let mut subshapes = Vec::new();
112 for shape in fields.values() {
113 subshapes.push(shape.clone());
114 }
115 if !rest.is_none() {
116 subshapes.push(rest.clone());
117 }
118 Shape::one(subshapes, locations.clone())
119 }
120
121 ShapeCase::Array { prefix, tail } => Shape::array(
122 prefix
123 .iter()
124 .map(|shape| shape.any_field(locations.clone())),
125 tail.any_field(locations.clone()),
126 locations.clone(),
127 ),
128
129 ShapeCase::One(shapes) => Shape::one(
130 shapes
131 .iter()
132 .map(|shape| shape.any_field(locations.clone())),
133 locations.clone(),
134 ),
135
136 ShapeCase::All(shapes) => Shape::all(
137 shapes
138 .iter()
139 .map(|shape| shape.any_field(locations.clone())),
140 locations.clone(),
141 ),
142
143 ShapeCase::Name(name, weak) => {
144 if let Some(named_shape) = weak.upgrade(name) {
145 named_shape.any_field(locations.clone())
146 } else {
147 Shape::new(
150 ShapeCase::Name(name.any_field(locations.clone()), weak.clone()),
151 locations.clone(),
152 )
153 }
154 }
155
156 ShapeCase::Error(Error { partial, .. }) => partial
157 .as_ref()
158 .map_or(Shape::none(), |shape| shape.any_field(locations.clone())),
159
160 _ => self.clone(),
163 };
164
165 child_shape.with_locations(locations.iter())
171 }
172
173 #[must_use]
176 pub fn item(&self, index: usize, locations: impl IntoIterator<Item = Location>) -> Shape {
177 let locations = locations.into_iter().collect::<Vec<_>>();
178
179 let child_shape = match self.case() {
180 ShapeCase::Array { prefix, tail } => {
181 if let Some(shape) = prefix.get(index) {
182 shape.clone().with_locations(locations.iter())
183 } else {
184 Shape::one([tail.clone(), Shape::none()], locations.clone())
187 }
188 }
189
190 ShapeCase::String(value) => {
191 if let Some(singleton) = value {
192 if let Some(ch) = singleton.chars().nth(index) {
193 Shape::string_value(ch.to_string().as_str(), locations.clone())
194 } else {
195 Shape::none()
196 }
197 } else {
198 Shape::one(
199 [Shape::string(locations.clone()), Shape::none()],
200 locations.clone(),
201 )
202 }
203 }
204
205 ShapeCase::One(shapes) => Shape::one(
206 shapes
207 .iter()
208 .map(|shape| shape.item(index, locations.clone())),
209 locations.clone(),
210 ),
211
212 ShapeCase::All(shapes) => Shape::all(
213 shapes
214 .iter()
215 .map(|shape| shape.item(index, locations.clone())),
216 locations.clone(),
217 ),
218
219 ShapeCase::Name(name, weak) => {
220 if let Some(named_shape) = weak.upgrade(name) {
221 named_shape.item(index, locations.clone())
222 } else {
223 Shape::new(
224 ShapeCase::Name(name.item(index, locations.clone()), weak.clone()),
225 locations.clone(),
226 )
227 }
228 }
229
230 ShapeCase::Error(Error { partial, .. }) => partial
231 .as_ref()
232 .map_or(Shape::none(), |shape| shape.item(index, locations.clone())),
233
234 ShapeCase::Unknown => self.clone(),
235
236 _ => Shape::none(),
237 };
238
239 self.propagate_names_to_child(child_shape.with_locations(locations.iter()), |name| {
240 name.item(index, locations.clone())
241 })
242 }
243
244 #[must_use]
247 pub fn any_item(&self, locations: impl IntoIterator<Item = Location>) -> Shape {
248 let locations = locations.into_iter().collect::<Vec<_>>();
249
250 let child_shape = match self.case() {
251 ShapeCase::Array { prefix, tail } => {
252 let mut subshapes = Vec::new();
253 for shape in prefix {
254 subshapes.push(shape.clone());
255 }
256 if !tail.is_none() {
257 subshapes.push(tail.clone());
258 }
259 Shape::one(subshapes, locations.clone())
260 }
261
262 ShapeCase::String(value) => {
263 if let Some(singleton) = value {
264 let mut subshapes = Vec::new();
265 for ch in singleton.chars() {
266 subshapes.push(Shape::string_value(ch.to_string().as_str(), []));
267 }
268 Shape::one(subshapes, locations.clone())
269 } else {
270 Shape::string(locations.clone())
271 }
272 }
273
274 ShapeCase::One(shapes) => Shape::one(
275 shapes.iter().map(|shape| shape.any_item(locations.clone())),
276 locations.clone(),
277 ),
278
279 ShapeCase::All(shapes) => Shape::all(
280 shapes.iter().map(|shape| shape.any_item(locations.clone())),
281 locations.clone(),
282 ),
283
284 ShapeCase::Name(name, weak) => {
285 if let Some(named_shape) = weak.upgrade(name) {
286 named_shape.any_item(locations.clone())
287 } else {
288 Shape::new(
289 ShapeCase::Name(name.any_item(locations.clone()), weak.clone()),
290 locations.clone(),
291 )
292 }
293 }
294
295 ShapeCase::Error(Error { partial, .. }) => partial
296 .as_ref()
297 .map_or(Shape::none(), |shape| shape.any_item(locations.clone())),
298
299 _ => self.clone(),
301 };
302
303 child_shape.with_locations(locations.iter())
309 }
310
311 #[must_use]
319 pub fn question(&self, locations: impl IntoIterator<Item = Location>) -> Shape {
320 let locations = locations.into_iter().collect::<Vec<_>>();
321
322 let child_shape = match self.case() {
323 ShapeCase::Null => Shape::none().with_locations(locations.iter()),
324
325 ShapeCase::One(shapes) => Shape::one(
326 shapes.iter().map(|shape| shape.question(locations.clone())),
327 locations.clone(),
328 ),
329
330 ShapeCase::All(shapes) => Shape::all(
331 shapes.iter().map(|shape| shape.question(locations.clone())),
332 locations.clone(),
333 ),
334
335 ShapeCase::Name(name, weak) => {
336 if let Some(named_shape) = weak.upgrade(name) {
337 named_shape.question(locations.clone())
338 } else {
339 Shape::new(
340 ShapeCase::Name(name.question(locations.clone()), weak.clone()),
341 locations.clone(),
342 )
343 }
344 }
345
346 ShapeCase::Error(Error { partial, .. }) => partial
347 .as_ref()
348 .map_or(Shape::none(), |shape| shape.question(locations.clone())),
349
350 _ => self.clone(),
353 };
354
355 self.propagate_names_to_child(child_shape.with_locations(locations.iter()), |name| {
356 name.question(locations.clone())
357 })
358 }
359
360 #[must_use]
367 pub fn not_none(&self, locations: impl IntoIterator<Item = Location>) -> Shape {
368 let locations = locations.into_iter().collect::<Vec<_>>();
369
370 let child_shape = match self.case() {
371 ShapeCase::None => Shape::never(locations.clone()),
372
373 ShapeCase::One(shapes) => Shape::one(
374 shapes.iter().map(|shape| shape.not_none(locations.clone())),
375 locations.clone(),
376 ),
377
378 ShapeCase::All(shapes) => Shape::all(
379 shapes.iter().map(|shape| shape.not_none(locations.clone())),
380 locations.clone(),
381 ),
382
383 ShapeCase::Name(name, weak) => {
384 if let Some(named_shape) = weak.upgrade(name) {
385 named_shape.not_none(locations.clone())
386 } else {
387 Shape::new(
388 ShapeCase::Name(name.not_none(locations.clone()), weak.clone()),
389 locations.clone(),
390 )
391 }
392 }
393
394 ShapeCase::Error(Error { partial, .. }) => partial
395 .as_ref()
396 .map_or(Shape::none(), |shape| shape.not_none(locations.clone())),
397
398 _ => self.clone(),
401 };
402
403 self.propagate_names_to_child(child_shape.with_locations(locations.iter()), |name| {
404 name.not_none(locations.clone())
405 })
406 }
407
408 #[must_use]
412 pub(crate) fn apply_name_case(
413 &self,
414 case: &NameCase,
415 locations: impl IntoIterator<Item = Location>,
416 ) -> Self {
417 match case {
418 NameCase::Base(name) => Self::name(name, locations),
419 NameCase::Field(_, name) => self.field(name, locations),
420 NameCase::AnyField(_) => self.any_field(locations),
421 NameCase::Item(_, index) => self.item(*index, locations),
422 NameCase::AnyItem(_) => self.any_item(locations),
423 NameCase::Question(_) => self.question(locations),
424 NameCase::NotNone(_) => self.not_none(locations),
425 }
426 }
427
428 #[must_use]
429 pub fn apply_name(&self, name: &Name) -> Self {
430 self.apply_name_case(name.case(), name.locs().cloned())
431 }
432}