1use super::Shape;
2use super::ShapeCase;
3use crate::location::Location;
4use crate::name::Name;
5use crate::name::NameCase;
6
7impl Shape {
8 #[must_use]
11 pub fn field(&self, field_name: &str, locations: impl IntoIterator<Item = Location>) -> Shape {
12 let locations = locations.into_iter().collect::<Vec<_>>();
13
14 let child_shape = match self.case() {
15 ShapeCase::Object { fields, rest } => {
16 if let Some(shape) = fields.get(field_name) {
17 shape.clone().with_locations(locations.iter())
18 } else {
19 Shape::one(
22 [rest.clone().with_locations(locations.iter()), Shape::none()],
23 locations.clone(),
24 )
25 }
26 }
27
28 ShapeCase::Array { prefix, tail } => {
29 let new_items = prefix
32 .iter()
33 .map(|shape| shape.field(field_name, locations.clone()))
34 .collect::<Vec<_>>();
35
36 let new_rest = tail.field(field_name, locations.clone());
37
38 if new_rest.is_none() && new_items.iter().all(Shape::is_none) {
42 Shape::none()
43 } else {
44 Shape::array(new_items, new_rest, locations.clone())
45 }
46 }
47
48 ShapeCase::One(shapes) => Shape::one(
49 shapes
50 .iter()
51 .map(|shape| shape.field(field_name, locations.clone())),
52 locations.clone(),
53 ),
54
55 ShapeCase::All(shapes) => Shape::all(
56 shapes
57 .iter()
58 .map(|shape| shape.field(field_name, locations.clone())),
59 locations.clone(),
60 ),
61
62 ShapeCase::Name(name, weak) => {
63 if let Some(named_shape) = weak.upgrade(name) {
64 named_shape.field(field_name, locations.clone())
65 } else {
66 Shape::new(
67 ShapeCase::Name(name.field(field_name, locations.clone()), weak.clone()),
68 locations.clone(),
69 )
70 }
71 }
72
73 ShapeCase::Unknown => self.clone().with_locations(locations.iter()),
74
75 _ => Shape::none(),
76 };
77
78 self.propagate_names_to_child(child_shape.with_locations(locations.iter()), |name| {
79 name.field(field_name, locations.clone())
80 })
81 }
82
83 fn propagate_names_to_child(
84 &self,
85 child_shape: Shape,
86 name_mapper: impl Fn(&Name) -> Name,
87 ) -> Shape {
88 let mapped_names = self.names().map(name_mapper);
89 let mut named = child_shape;
90 for name in mapped_names {
91 named = named.with_name(&name);
92 }
93 named
94 }
95
96 #[must_use]
99 pub fn any_field(&self, locations: impl IntoIterator<Item = Location>) -> Shape {
100 let locations = locations.into_iter().collect::<Vec<_>>();
101
102 let child_shape = match self.case() {
103 ShapeCase::Object { fields, rest } => {
104 let mut subshapes = Vec::new();
105 for shape in fields.values() {
106 subshapes.push(shape.clone());
107 }
108 if !rest.is_none() {
109 subshapes.push(rest.clone());
110 }
111 Shape::one(subshapes, locations.clone())
112 }
113
114 ShapeCase::Array { prefix, tail } => Shape::array(
115 prefix
116 .iter()
117 .map(|shape| shape.any_field(locations.clone())),
118 tail.any_field(locations.clone()),
119 locations.clone(),
120 ),
121
122 ShapeCase::One(shapes) => Shape::one(
123 shapes
124 .iter()
125 .map(|shape| shape.any_field(locations.clone())),
126 locations.clone(),
127 ),
128
129 ShapeCase::All(shapes) => Shape::all(
130 shapes
131 .iter()
132 .map(|shape| shape.any_field(locations.clone())),
133 locations.clone(),
134 ),
135
136 ShapeCase::Name(name, weak) => {
137 if let Some(named_shape) = weak.upgrade(name) {
138 named_shape.any_field(locations.clone())
139 } else {
140 Shape::new(
143 ShapeCase::Name(name.any_field(locations.clone()), weak.clone()),
144 locations.clone(),
145 )
146 }
147 }
148
149 _ => self.clone(),
152 };
153
154 child_shape.with_locations(locations.iter())
160 }
161
162 #[must_use]
165 pub fn item(&self, index: usize, locations: impl IntoIterator<Item = Location>) -> Shape {
166 let locations = locations.into_iter().collect::<Vec<_>>();
167
168 let child_shape = match self.case() {
169 ShapeCase::Array { prefix, tail } => {
170 if let Some(shape) = prefix.get(index) {
171 shape.clone().with_locations(locations.iter())
172 } else {
173 Shape::one([tail.clone(), Shape::none()], locations.clone())
176 }
177 }
178
179 ShapeCase::String(value) => {
180 if let Some(singleton) = value {
181 if let Some(ch) = singleton.chars().nth(index) {
182 Shape::string_value(ch.to_string().as_str(), locations.clone())
183 } else {
184 Shape::none()
185 }
186 } else {
187 Shape::one(
188 [Shape::string(locations.clone()), Shape::none()],
189 locations.clone(),
190 )
191 }
192 }
193
194 ShapeCase::One(shapes) => Shape::one(
195 shapes
196 .iter()
197 .map(|shape| shape.item(index, locations.clone())),
198 locations.clone(),
199 ),
200
201 ShapeCase::All(shapes) => Shape::all(
202 shapes
203 .iter()
204 .map(|shape| shape.item(index, locations.clone())),
205 locations.clone(),
206 ),
207
208 ShapeCase::Name(name, weak) => {
209 if let Some(named_shape) = weak.upgrade(name) {
210 named_shape.item(index, locations.clone())
211 } else {
212 Shape::new(
213 ShapeCase::Name(name.item(index, locations.clone()), weak.clone()),
214 locations.clone(),
215 )
216 }
217 }
218
219 ShapeCase::Unknown => self.clone(),
220
221 _ => Shape::none(),
222 };
223
224 self.propagate_names_to_child(child_shape.with_locations(locations.iter()), |name| {
225 name.item(index, locations.clone())
226 })
227 }
228
229 #[must_use]
232 pub fn any_item(&self, locations: impl IntoIterator<Item = Location>) -> Shape {
233 let locations = locations.into_iter().collect::<Vec<_>>();
234
235 let child_shape = match self.case() {
236 ShapeCase::Array { prefix, tail } => {
237 let mut subshapes = Vec::new();
238 for shape in prefix {
239 subshapes.push(shape.clone());
240 }
241 if !tail.is_none() {
242 subshapes.push(tail.clone());
243 }
244 Shape::one(subshapes, locations.clone())
245 }
246
247 ShapeCase::String(value) => {
248 if let Some(singleton) = value {
249 let mut subshapes = Vec::new();
250 for ch in singleton.chars() {
251 subshapes.push(Shape::string_value(ch.to_string().as_str(), []));
252 }
253 Shape::one(subshapes, locations.clone())
254 } else {
255 Shape::string(locations.clone())
256 }
257 }
258
259 ShapeCase::One(shapes) => Shape::one(
260 shapes.iter().map(|shape| shape.any_item(locations.clone())),
261 locations.clone(),
262 ),
263
264 ShapeCase::All(shapes) => Shape::all(
265 shapes.iter().map(|shape| shape.any_item(locations.clone())),
266 locations.clone(),
267 ),
268
269 ShapeCase::Name(name, weak) => {
270 if let Some(named_shape) = weak.upgrade(name) {
271 named_shape.any_item(locations.clone())
272 } else {
273 Shape::new(
274 ShapeCase::Name(name.any_item(locations.clone()), weak.clone()),
275 locations.clone(),
276 )
277 }
278 }
279
280 _ => self.clone(),
282 };
283
284 child_shape.with_locations(locations.iter())
290 }
291
292 #[must_use]
300 pub fn question(&self, locations: impl IntoIterator<Item = Location>) -> Shape {
301 let locations = locations.into_iter().collect::<Vec<_>>();
302
303 let child_shape = match self.case() {
304 ShapeCase::Null => Shape::none().with_locations(locations.iter()),
305
306 ShapeCase::One(shapes) => Shape::one(
307 shapes.iter().map(|shape| shape.question(locations.clone())),
308 locations.clone(),
309 ),
310
311 ShapeCase::All(shapes) => Shape::all(
312 shapes.iter().map(|shape| shape.question(locations.clone())),
313 locations.clone(),
314 ),
315
316 ShapeCase::Name(name, weak) => {
317 if let Some(named_shape) = weak.upgrade(name) {
318 named_shape.question(locations.clone())
319 } else {
320 Shape::new(
321 ShapeCase::Name(name.question(locations.clone()), weak.clone()),
322 locations.clone(),
323 )
324 }
325 }
326
327 _ => self.clone(),
330 };
331
332 self.propagate_names_to_child(child_shape.with_locations(locations.iter()), |name| {
333 name.question(locations.clone())
334 })
335 }
336
337 #[must_use]
344 pub fn not_none(&self, locations: impl IntoIterator<Item = Location>) -> Shape {
345 let locations = locations.into_iter().collect::<Vec<_>>();
346
347 let child_shape = match self.case() {
348 ShapeCase::None => Shape::never(locations.clone()),
349
350 ShapeCase::One(shapes) => Shape::one(
351 shapes.iter().map(|shape| shape.not_none(locations.clone())),
352 locations.clone(),
353 ),
354
355 ShapeCase::All(shapes) => Shape::all(
356 shapes.iter().map(|shape| shape.not_none(locations.clone())),
357 locations.clone(),
358 ),
359
360 ShapeCase::Name(name, weak) => {
361 if let Some(named_shape) = weak.upgrade(name) {
362 named_shape.not_none(locations.clone())
363 } else {
364 Shape::new(
365 ShapeCase::Name(name.not_none(locations.clone()), weak.clone()),
366 locations.clone(),
367 )
368 }
369 }
370
371 _ => self.clone(),
374 };
375
376 self.propagate_names_to_child(child_shape.with_locations(locations.iter()), |name| {
377 name.not_none(locations.clone())
378 })
379 }
380
381 #[must_use]
385 pub(crate) fn apply_name_case(
386 &self,
387 case: &NameCase,
388 locations: impl IntoIterator<Item = Location>,
389 ) -> Self {
390 match case {
391 NameCase::Base(name) => Self::name(name, locations),
392 NameCase::Field(_, name) => self.field(name, locations),
393 NameCase::AnyField(_) => self.any_field(locations),
394 NameCase::Item(_, index) => self.item(*index, locations),
395 NameCase::AnyItem(_) => self.any_item(locations),
396 NameCase::Question(_) => self.question(locations),
397 NameCase::NotNone(_) => self.not_none(locations),
398 }
399 }
400
401 #[must_use]
402 pub fn apply_name(&self, name: &Name) -> Self {
403 self.apply_name_case(name.case(), name.locs().cloned())
404 }
405}