1use std::ops::{Deref, DerefMut};
27
28use crate::path::ValuePath;
29use crate::value::{
30 Kind, Value,
31 kind::{Collection, Field, Index, merge},
32};
33
34#[derive(Debug, Clone, Eq, PartialEq)]
35pub enum Fallibility {
36 CannotFail,
37 MightFail,
38 AlwaysFails,
39}
40
41impl Fallibility {
42 #[must_use]
43 pub fn merge(left: &Self, right: &Self) -> Self {
51 use Fallibility::{AlwaysFails, CannotFail, MightFail};
52
53 match (left, right) {
54 (AlwaysFails, _) | (_, AlwaysFails) => AlwaysFails,
55 (MightFail, _) | (_, MightFail) => MightFail,
56 _ => CannotFail,
57 }
58 }
59}
60
61#[derive(Default, Debug, Clone, Eq, PartialEq)]
62pub enum Purity {
63 #[default]
66 Pure,
67 Impure,
69}
70
71impl Purity {
72 #[must_use]
73 fn merge(left: &Self, right: &Self) -> Self {
75 use Purity::{Impure, Pure};
76
77 match (left, right) {
78 (Pure, Pure) => Pure,
79 _ => Impure,
80 }
81 }
82}
83
84#[derive(Debug, Clone, Eq, PartialEq)]
87pub struct TypeDef {
88 fallibility: Fallibility,
98
99 kind: Kind,
101
102 purity: Purity,
105
106 returns: Kind,
108}
109
110impl Deref for TypeDef {
111 type Target = Kind;
112
113 fn deref(&self) -> &Self::Target {
114 &self.kind
115 }
116}
117
118impl DerefMut for TypeDef {
119 fn deref_mut(&mut self) -> &mut Self::Target {
120 &mut self.kind
121 }
122}
123
124impl TypeDef {
125 #[must_use]
126 pub fn kind(&self) -> &Kind {
127 &self.kind
128 }
129
130 #[must_use]
131 pub fn kind_mut(&mut self) -> &mut Kind {
132 &mut self.kind
133 }
134
135 #[must_use]
136 pub fn returns(&self) -> &Kind {
137 &self.returns
138 }
139
140 #[must_use]
141 pub fn returns_mut(&mut self) -> &mut Kind {
142 &mut self.returns
143 }
144
145 #[must_use]
146 pub fn at_path<'a>(&self, path: impl ValuePath<'a>) -> TypeDef {
147 Self {
148 fallibility: self.fallibility.clone(),
149 kind: self.kind.at_path(path),
150 purity: self.purity.clone(),
151 returns: self.returns.clone(),
152 }
153 }
154
155 #[inline]
156 #[must_use]
157 pub fn fallible(mut self) -> Self {
158 self.fallibility = Fallibility::MightFail;
159 self
160 }
161
162 #[inline]
163 #[must_use]
164 pub fn infallible(mut self) -> Self {
165 self.fallibility = Fallibility::CannotFail;
166 self
167 }
168
169 #[inline]
170 #[must_use]
171 pub fn always_fails(mut self) -> Self {
172 self.fallibility = Fallibility::AlwaysFails;
173 self
174 }
175
176 #[inline]
177 #[must_use]
178 pub fn maybe_fallible(mut self, might_fail: bool) -> Self {
180 if might_fail {
181 self.fallibility = Fallibility::MightFail;
182 } else {
183 self.fallibility = Fallibility::CannotFail;
184 }
185 self
186 }
187
188 #[inline]
189 #[must_use]
190 pub fn with_fallibility(mut self, fallibility: Fallibility) -> Self {
191 self.fallibility = fallibility;
192 self
193 }
194
195 #[inline]
196 #[must_use]
197 pub fn pure(mut self) -> Self {
198 self.purity = Purity::Pure;
199 self
200 }
201
202 #[inline]
203 #[must_use]
204 pub fn impure(mut self) -> Self {
205 self.purity = Purity::Impure;
206 self
207 }
208
209 #[inline]
210 #[must_use]
211 pub fn any() -> Self {
212 Kind::any().into()
213 }
214
215 #[inline]
216 #[must_use]
217 pub fn bytes() -> Self {
218 Kind::bytes().into()
219 }
220
221 #[inline]
222 #[must_use]
223 pub fn or_bytes(mut self) -> Self {
224 self.kind.add_bytes();
225 self
226 }
227
228 #[inline]
229 #[must_use]
230 pub fn integer() -> Self {
231 Kind::integer().into()
232 }
233
234 #[inline]
235 #[must_use]
236 pub fn or_integer(mut self) -> Self {
237 self.kind.add_integer();
238 self
239 }
240
241 #[inline]
242 #[must_use]
243 pub fn float() -> Self {
244 Kind::float().into()
245 }
246
247 #[inline]
248 #[must_use]
249 pub fn or_float(mut self) -> Self {
250 self.kind.add_float();
251 self
252 }
253
254 #[inline]
255 #[must_use]
256 pub fn boolean() -> Self {
257 Kind::boolean().into()
258 }
259
260 #[inline]
261 #[must_use]
262 pub fn or_boolean(mut self) -> Self {
263 self.kind.add_boolean();
264 self
265 }
266
267 #[inline]
268 #[must_use]
269 pub fn timestamp() -> Self {
270 Kind::timestamp().into()
271 }
272
273 #[inline]
274 #[must_use]
275 pub fn or_timestamp(mut self) -> Self {
276 self.kind.add_timestamp();
277 self
278 }
279
280 #[inline]
281 #[must_use]
282 pub fn regex() -> Self {
283 Kind::regex().into()
284 }
285
286 #[inline]
287 #[must_use]
288 pub fn or_regex(mut self) -> Self {
289 self.kind.add_regex();
290 self
291 }
292
293 #[inline]
294 #[must_use]
295 pub fn null() -> Self {
296 Kind::null().into()
297 }
298
299 #[inline]
300 #[must_use]
301 pub fn or_null(mut self) -> Self {
302 self.kind.add_null();
303 self
304 }
305
306 #[inline]
307 #[must_use]
308 pub fn undefined() -> Self {
309 Kind::undefined().into()
310 }
311
312 #[inline]
313 #[must_use]
314 pub fn or_undefined(mut self) -> Self {
315 self.kind.add_undefined();
316 self
317 }
318
319 #[inline]
320 #[must_use]
321 pub fn never() -> Self {
322 Kind::never().into()
323 }
324
325 #[inline]
326 #[must_use]
327 pub fn add_null(mut self) -> Self {
328 self.kind.add_null();
329 self
330 }
331
332 #[inline]
333 pub fn array(collection: impl Into<Collection<Index>>) -> Self {
334 Kind::array(collection).into()
335 }
336
337 #[inline]
338 #[must_use]
339 pub fn or_array(mut self, collection: impl Into<Collection<Index>>) -> Self {
340 self.kind.add_array(collection);
341 self
342 }
343
344 #[inline]
352 #[must_use]
353 pub fn restrict_array(self) -> Self {
354 let fallible = self.fallibility;
355 let collection = match self.kind.into_array() {
356 Some(array) => array,
357 None => Collection::any(),
358 };
359
360 Self {
361 fallibility: fallible,
362 kind: Kind::array(collection),
363 purity: self.purity.clone(),
364 returns: self.returns.clone(),
365 }
366 }
367
368 #[inline]
369 pub fn object(collection: impl Into<Collection<Field>>) -> Self {
370 Kind::object(collection).into()
371 }
372
373 #[inline]
374 #[must_use]
375 pub fn or_object(mut self, collection: impl Into<Collection<Field>>) -> Self {
376 self.kind.add_object(collection);
377 self
378 }
379
380 #[inline]
388 #[must_use]
389 pub fn restrict_object(self) -> Self {
390 let fallible = self.fallibility;
391 let collection = match self.kind.into_object() {
392 Some(object) => object,
393 None => Collection::any(),
394 };
395
396 Self {
397 fallibility: fallible,
398 kind: Kind::object(collection),
399 purity: self.purity.clone(),
400 returns: self.returns.clone(),
401 }
402 }
403
404 #[inline]
405 #[must_use]
406 pub fn with_kind(mut self, kind: Kind) -> Self {
407 self.kind = kind;
408 self
409 }
410
411 #[inline]
412 #[must_use]
413 pub fn with_returns(mut self, returns: Kind) -> Self {
414 self.returns = returns;
415 self
416 }
417
418 #[must_use]
423 pub fn upgrade_undefined(mut self) -> Self {
424 self.kind = self.kind.upgrade_undefined();
425 self
426 }
427
428 #[must_use]
434 pub fn collect_subtypes(mut self) -> Self {
435 if let Some(object) = self.kind.as_object_mut() {
436 object.set_unknown(Kind::undefined());
437 object.anonymize();
438 }
439 if let Some(array) = self.kind.as_array_mut() {
440 array.set_unknown(Kind::undefined());
441 array.anonymize();
442 }
443
444 self
445 }
446
447 #[must_use]
450 pub fn is_fallible(&self) -> bool {
451 self.fallibility == Fallibility::MightFail || self.fallibility == Fallibility::AlwaysFails
452 }
453
454 #[must_use]
455 pub fn is_infallible(&self) -> bool {
456 !self.is_fallible()
457 }
458
459 #[must_use]
460 pub fn is_pure(&self) -> bool {
461 self.purity == Purity::Pure
462 }
463
464 #[must_use]
465 pub fn is_impure(&self) -> bool {
466 self.purity == Purity::Impure
467 }
468
469 #[must_use]
472 pub fn fallible_unless(mut self, kind: impl Into<Kind>) -> Self {
473 let kind = kind.into();
474 if kind.is_superset(&self.kind).is_err() {
475 self.fallibility = Fallibility::MightFail;
476 }
477
478 self
479 }
480
481 #[must_use]
482 pub fn union(mut self, other: Self) -> Self {
483 self.fallibility = Fallibility::merge(&self.fallibility, &other.fallibility);
484 self.kind = self.kind.union(other.kind);
485 self.purity = Purity::merge(&self.purity, &other.purity);
486 self.returns = self.returns.union(other.returns);
487 self
488 }
489
490 pub fn merge(&mut self, other: Self, strategy: merge::Strategy) {
492 self.fallibility = Fallibility::merge(&self.fallibility, &other.fallibility);
493 self.kind.merge(other.kind, strategy);
494 self.purity = Purity::merge(&self.purity, &other.purity);
495 self.returns = self.returns.union(other.returns);
496 }
497
498 #[must_use]
499 pub fn with_type_inserted<'a>(self, path: impl ValuePath<'a>, other: Self) -> Self {
500 let mut kind = self.kind;
501 kind.insert(path, other.kind);
502 Self {
503 fallibility: Fallibility::merge(&self.fallibility, &other.fallibility),
504 kind,
505 purity: Purity::merge(&self.purity, &other.purity),
506 returns: self.returns.clone(),
507 }
508 }
509
510 #[must_use]
511 pub fn merge_overwrite(mut self, other: Self) -> Self {
513 self.merge(
514 other,
515 merge::Strategy {
516 collisions: merge::CollisionStrategy::Overwrite,
517 },
518 );
519 self
520 }
521}
522
523impl From<Kind> for TypeDef {
524 fn from(kind: Kind) -> Self {
525 Self {
526 fallibility: Fallibility::CannotFail,
527 kind,
528 purity: Purity::Pure,
529 returns: Kind::never(),
530 }
531 }
532}
533
534impl From<TypeDef> for Kind {
535 fn from(type_def: TypeDef) -> Self {
536 type_def.kind
537 }
538}
539
540#[derive(Debug, Clone, PartialEq)]
541pub(crate) struct Details {
542 pub(crate) type_def: TypeDef,
543 pub(crate) value: Option<Value>,
544}
545
546impl Details {
547 pub(crate) fn merge(self, other: Self) -> Self {
549 Self {
550 type_def: self.type_def.union(other.type_def),
551 value: if self.value == other.value {
552 self.value
553 } else {
554 None
555 },
556 }
557 }
558}
559
560#[cfg(test)]
561mod test {
562 use super::Fallibility::*;
563 use super::Purity::*;
564 use super::*;
565
566 #[test]
567 fn merge_details_same_literal() {
568 let a = Details {
569 type_def: TypeDef::integer(),
570 value: Some(Value::from(5)),
571 };
572 let b = Details {
573 type_def: TypeDef::float(),
574 value: Some(Value::from(5)),
575 };
576 assert_eq!(
577 a.merge(b),
578 Details {
579 type_def: TypeDef::integer().or_float(),
580 value: Some(Value::from(5)),
581 }
582 );
583 }
584
585 #[test]
586 fn merge_details_different_literal() {
587 let a = Details {
588 type_def: TypeDef::any(),
589 value: Some(Value::from(5)),
590 };
591 let b = Details {
592 type_def: TypeDef::object(Collection::empty()),
593 value: Some(Value::from(6)),
594 };
595 assert_eq!(
596 a.merge(b),
597 Details {
598 type_def: TypeDef::any(),
599 value: None,
600 }
601 );
602 }
603
604 #[test]
605 fn merge_fallibility_instances() {
606 assert_eq!(Fallibility::merge(&AlwaysFails, &MightFail), AlwaysFails);
607 assert_eq!(Fallibility::merge(&AlwaysFails, &CannotFail), AlwaysFails);
608 assert_eq!(
609 Fallibility::merge(&Fallibility::merge(&CannotFail, &MightFail), &AlwaysFails),
610 AlwaysFails
611 );
612
613 assert_eq!(Fallibility::merge(&MightFail, &MightFail), MightFail);
614 assert_eq!(Fallibility::merge(&CannotFail, &MightFail), MightFail);
615
616 assert_eq!(Fallibility::merge(&CannotFail, &CannotFail), CannotFail);
617 }
618
619 #[test]
620 fn merge_purity() {
621 assert_eq!(Purity::merge(&Pure, &Impure), Impure);
622 assert_eq!(Purity::merge(&Impure, &Pure), Impure);
623 assert_eq!(Purity::merge(&Impure, &Impure), Impure);
624 assert_eq!(Purity::merge(&Pure, &Pure), Pure);
625 }
626}