• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

naomijub / serde_json_shape / 15768801561

20 Jun 2025 12:52AM UTC coverage: 42.517% (-1.8%) from 44.305%
15768801561

Pull #3

github

web-flow
Merge 60e32ef7e into 3f39669fb
Pull Request #3: Implements Tuple

68 of 188 new or added lines in 5 files covered. (36.17%)

10 existing lines in 4 files now uncovered.

429 of 1009 relevant lines covered (42.52%)

2.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

39.7
/src/value/subtypes.rs
1
use crate::value::Value;
2

3
/// Simple helper phantom struct to determine if `JsonShape` is of specific subtype `Null`.
4
pub struct Null;
5
/// Simple helper phantom struct to determine if `JsonShape` is of specific subtype `Number`.
6
pub struct Number;
7
/// Simple helper phantom struct to determine if `JsonShape` is of specific subtype `Boolean`.
8
pub struct Boolean;
9
/// Simple helper phantom struct to determine if `JsonShape` is of specific subtype `String`.
10
pub struct String;
11
/// Simple helper phantom struct to determine if `JsonShape` is of specific subtype `Array`.
12
pub struct Array;
13
/// Simple helper phantom struct to determine if `JsonShape` is of specific subtype `Object`.
14
pub struct Object;
15
/// Simple helper phantom struct to determine if `JsonShape` is of specific subtype `OneOf`.
16
pub struct OneOf;
17

18
/// Simple helper struct to determine if `JsonShape` is of specific optional subtype.
19
pub struct Optional<U>(std::marker::PhantomData<U>);
20

21
mod private {
22
    use crate::value::Value;
23

24
    pub trait Sealed {}
25
    impl Sealed for Value {}
26
}
27

28
impl Value {
29
    #[must_use]
30
    /// Cheecks if [`JsonShape::Tuple`] is tuple containing `&[JsonShape]` in the same order and type.
31
    pub fn is_tuple_of(&self, types: &[Value]) -> bool {
1✔
32
        if let Value::Tuple { elements, .. } = self {
2✔
33
            elements.len() == types.len() && elements.iter().zip(types.iter()).all(|(a, b)| a == b)
4✔
34
        } else {
35
            false
1✔
36
        }
37
    }
38
}
39

40
/// Checks if [`JsonShape`] is an Array of `T`
41
pub trait IsArrayOf<T>: private::Sealed {
42
    /// Checks if [`JsonShape`] is an Array of `T`
43
    /// - `value.is_array_of::<Null>()`.
44
    #[allow(dead_code)]
45
    fn is_array_of(&self) -> bool;
46
}
47

48
/// Checks if [`JsonShape`] is `OneOf` containing `T`
49
pub trait IsOneOf<T>: private::Sealed {
50
    /// Checks if [`JsonShape`] is `OneOf` containing `T`
51
    /// - `value.is_one_of::<Null>()`.
52
    fn is_one_of(&self) -> bool;
53
}
54

55
/// Checks if [`JsonShape`] is `Object` containing `key: &str` and  `value: T`
56
pub trait IsObjectOf<T>: private::Sealed {
57
    /// Checks if [`JsonShape`] is `Object` containing `key: &str` and  `value: T`
58
    /// - `value.is_object_of::<Null>("key_1")`.
59
    #[allow(dead_code)]
60
    fn is_object_of(&self, key: &str) -> bool;
61
}
62

63
// ARRAY
64
impl IsArrayOf<Null> for Value {
65
    fn is_array_of(&self) -> bool {
1✔
66
        if let Value::Array { r#type, .. } = self {
1✔
67
            **r#type == Value::Null
2✔
68
        } else {
69
            false
×
70
        }
71
    }
72
}
73

74
impl IsArrayOf<Number> for Value {
75
    fn is_array_of(&self) -> bool {
1✔
76
        if let Value::Array { r#type, .. } = self {
1✔
77
            matches!(**r#type, Value::Number { optional: false })
2✔
78
        } else {
79
            false
×
80
        }
81
    }
82
}
83

84
impl IsArrayOf<Optional<Number>> for Value {
85
    fn is_array_of(&self) -> bool {
1✔
86
        if let Value::Array { r#type, .. } = self {
1✔
87
            matches!(**r#type, Value::Number { optional: true })
2✔
88
        } else {
89
            false
×
90
        }
91
    }
92
}
93

94
impl IsArrayOf<String> for Value {
95
    fn is_array_of(&self) -> bool {
1✔
96
        if let Value::Array { r#type, .. } = self {
1✔
97
            matches!(**r#type, Value::String { optional: false })
2✔
98
        } else {
99
            false
×
100
        }
101
    }
102
}
103

104
impl IsArrayOf<Optional<String>> for Value {
105
    fn is_array_of(&self) -> bool {
1✔
106
        if let Value::Array { r#type, .. } = self {
1✔
107
            matches!(**r#type, Value::String { optional: true })
1✔
108
        } else {
109
            false
×
110
        }
111
    }
112
}
113

114
impl IsArrayOf<Boolean> for Value {
115
    fn is_array_of(&self) -> bool {
1✔
116
        if let Value::Array { r#type, .. } = self {
1✔
117
            matches!(**r#type, Value::Bool { optional: false })
2✔
118
        } else {
119
            false
×
120
        }
121
    }
122
}
123

124
impl IsArrayOf<Optional<Boolean>> for Value {
125
    fn is_array_of(&self) -> bool {
×
126
        if let Value::Array { r#type, .. } = self {
×
127
            matches!(**r#type, Value::Bool { optional: true })
×
128
        } else {
129
            false
×
130
        }
131
    }
132
}
133

134
impl IsArrayOf<Array> for Value {
135
    fn is_array_of(&self) -> bool {
×
136
        if let Value::Array { r#type, .. } = self {
×
137
            matches!(
×
138
                **r#type,
×
139
                Value::Array {
140
                    optional: false,
141
                    ..
142
                }
143
            )
144
        } else {
145
            false
×
146
        }
147
    }
148
}
149

150
impl IsArrayOf<Optional<Array>> for Value {
151
    fn is_array_of(&self) -> bool {
×
152
        if let Value::Array { r#type, .. } = self {
×
153
            matches!(**r#type, Value::Array { optional: true, .. })
×
154
        } else {
155
            false
×
156
        }
157
    }
158
}
159

160
impl IsArrayOf<Object> for Value {
161
    fn is_array_of(&self) -> bool {
×
162
        if let Value::Array { r#type, .. } = self {
×
163
            matches!(
×
164
                **r#type,
×
165
                Value::Object {
166
                    optional: false,
167
                    ..
168
                }
169
            )
170
        } else {
171
            false
×
172
        }
173
    }
174
}
175

176
impl IsArrayOf<Optional<Object>> for Value {
177
    fn is_array_of(&self) -> bool {
×
178
        if let Value::Array { r#type, .. } = self {
×
179
            matches!(**r#type, Value::Object { optional: true, .. })
×
180
        } else {
181
            false
×
182
        }
183
    }
184
}
185

186
impl IsArrayOf<OneOf> for Value {
187
    fn is_array_of(&self) -> bool {
×
188
        if let Value::Array { r#type, .. } = self {
×
189
            matches!(
×
190
                **r#type,
×
191
                Value::OneOf {
192
                    optional: false,
193
                    ..
194
                }
195
            )
196
        } else {
197
            false
×
198
        }
199
    }
200
}
201

202
impl IsArrayOf<Optional<OneOf>> for Value {
203
    fn is_array_of(&self) -> bool {
×
204
        if let Value::Array { r#type, .. } = self {
×
205
            matches!(**r#type, Value::OneOf { optional: true, .. })
×
206
        } else {
207
            false
×
208
        }
209
    }
210
}
211

212
// OneOf
213
impl IsOneOf<Null> for Value {
214
    fn is_one_of(&self) -> bool {
×
215
        if let Value::OneOf { variants, .. } = self {
×
216
            variants.contains(&Value::Null)
×
217
        } else {
218
            false
×
219
        }
220
    }
221
}
222

223
impl IsOneOf<Number> for Value {
224
    fn is_one_of(&self) -> bool {
4✔
225
        if let Value::OneOf { variants, .. } = self {
4✔
226
            variants
227
                .iter()
228
                .any(|variant| matches!(&variant, &Value::Number { optional: false }))
4✔
229
        } else {
230
            false
4✔
231
        }
232
    }
233
}
234

235
impl IsOneOf<String> for Value {
236
    fn is_one_of(&self) -> bool {
4✔
237
        if let Value::OneOf { variants, .. } = self {
4✔
238
            variants
239
                .iter()
240
                .any(|variant| matches!(&variant, &Value::String { optional: false }))
6✔
241
        } else {
242
            false
4✔
243
        }
244
    }
245
}
246

247
impl IsOneOf<Boolean> for Value {
248
    fn is_one_of(&self) -> bool {
4✔
249
        if let Value::OneOf { variants, .. } = self {
4✔
250
            variants
251
                .iter()
252
                .any(|variant| matches!(&variant, &Value::Bool { optional: false }))
6✔
253
        } else {
254
            false
4✔
255
        }
256
    }
257
}
258

259
impl IsOneOf<Array> for Value {
260
    fn is_one_of(&self) -> bool {
×
261
        if let Value::OneOf { variants, .. } = self {
×
262
            variants.iter().any(|variant| {
×
263
                matches!(
×
264
                    &variant,
×
265
                    &Value::Array {
266
                        optional: false,
267
                        ..
268
                    }
269
                )
270
            })
271
        } else {
272
            false
×
273
        }
274
    }
275
}
276

277
impl IsOneOf<Object> for Value {
278
    fn is_one_of(&self) -> bool {
×
279
        if let Value::OneOf { variants, .. } = self {
×
280
            variants.iter().any(|variant| {
×
281
                matches!(
×
282
                    &variant,
×
283
                    &Value::Object {
284
                        optional: false,
285
                        ..
286
                    }
287
                )
288
            })
289
        } else {
290
            false
×
291
        }
292
    }
293
}
294

295
impl IsOneOf<OneOf> for Value {
296
    fn is_one_of(&self) -> bool {
×
297
        if let Value::OneOf { variants, .. } = self {
×
298
            variants.iter().any(|variant| {
×
299
                matches!(
×
300
                    &variant,
×
301
                    &Value::OneOf {
302
                        optional: false,
303
                        ..
304
                    }
305
                )
306
            })
307
        } else {
308
            false
×
309
        }
310
    }
311
}
312

313
impl IsOneOf<Optional<Number>> for Value {
314
    fn is_one_of(&self) -> bool {
4✔
315
        if let Value::OneOf { variants, .. } = self {
8✔
316
            variants
1✔
317
                .iter()
1✔
318
                .any(|variant| matches!(&variant, &Value::Number { .. }))
3✔
319
                && variants.contains(&Value::Null)
1✔
320
        } else {
321
            false
4✔
322
        }
323
    }
324
}
325

326
impl IsOneOf<Optional<String>> for Value {
327
    fn is_one_of(&self) -> bool {
3✔
328
        if let Value::OneOf { variants, .. } = self {
6✔
329
            variants
2✔
330
                .iter()
1✔
331
                .any(|variant| matches!(&variant, &Value::String { .. }))
3✔
332
                && variants.contains(&Value::Null)
1✔
333
        } else {
334
            false
3✔
335
        }
336
    }
337
}
338

339
impl IsOneOf<Optional<Boolean>> for Value {
340
    fn is_one_of(&self) -> bool {
4✔
341
        if let Value::OneOf { variants, .. } = self {
8✔
342
            variants
1✔
343
                .iter()
1✔
344
                .any(|variant| matches!(&variant, &Value::Bool { .. }))
3✔
345
                && variants.contains(&Value::Null)
1✔
346
        } else {
347
            false
4✔
348
        }
349
    }
350
}
351

352
impl IsOneOf<Optional<Array>> for Value {
353
    fn is_one_of(&self) -> bool {
×
354
        if let Value::OneOf { variants, .. } = self {
×
UNCOV
355
            variants
×
UNCOV
356
                .iter()
×
NEW
357
                .any(|variant| matches!(&variant, &Value::Array { .. }))
×
NEW
358
                && variants.contains(&Value::Null)
×
359
        } else {
360
            false
×
361
        }
362
    }
363
}
364

365
impl IsOneOf<Optional<Object>> for Value {
366
    fn is_one_of(&self) -> bool {
×
367
        if let Value::OneOf { variants, .. } = self {
×
UNCOV
368
            variants
×
UNCOV
369
                .iter()
×
NEW
370
                .any(|variant| matches!(&variant, &Value::Object { .. }))
×
NEW
371
                && variants.contains(&Value::Null)
×
372
        } else {
373
            false
×
374
        }
375
    }
376
}
377

378
impl IsOneOf<Optional<OneOf>> for Value {
379
    fn is_one_of(&self) -> bool {
1✔
380
        if let Value::OneOf { variants, optional } = self {
1✔
381
            variants
2✔
382
                .iter()
1✔
383
                .any(|variant| matches!(&variant, &Value::OneOf { optional: true, .. }))
3✔
384
                || *optional
1✔
385
        } else {
386
            false
×
387
        }
388
    }
389
}
390

391
// Object
392
impl IsObjectOf<Null> for Value {
393
    fn is_object_of(&self, key: &str) -> bool {
×
394
        if let Value::Object { content, .. } = self {
×
395
            content
396
                .iter()
397
                .any(|(k, value)| k == key && matches!(&value, &Value::Null))
×
398
        } else {
399
            false
×
400
        }
401
    }
402
}
403

404
impl IsObjectOf<Number> for Value {
405
    fn is_object_of(&self, key: &str) -> bool {
1✔
406
        if let Value::Object { content, .. } = self {
1✔
407
            content
408
                .iter()
409
                .any(|(k, value)| k == key && matches!(&value, &Value::Number { optional: false }))
3✔
410
        } else {
411
            false
×
412
        }
413
    }
414
}
415

416
impl IsObjectOf<String> for Value {
417
    fn is_object_of(&self, key: &str) -> bool {
1✔
418
        if let Value::Object { content, .. } = self {
1✔
419
            content
420
                .iter()
421
                .any(|(k, value)| k == key && matches!(&value, &Value::String { optional: false }))
3✔
422
        } else {
423
            false
×
424
        }
425
    }
426
}
427

428
impl IsObjectOf<Boolean> for Value {
429
    fn is_object_of(&self, key: &str) -> bool {
1✔
430
        if let Value::Object { content, .. } = self {
1✔
431
            content
432
                .iter()
433
                .any(|(k, value)| k == key && matches!(&value, &Value::Bool { optional: false }))
3✔
434
        } else {
435
            false
×
436
        }
437
    }
438
}
439

440
impl IsObjectOf<Array> for Value {
441
    fn is_object_of(&self, key: &str) -> bool {
×
442
        if let Value::Object { content, .. } = self {
×
443
            content.iter().any(|(k, value)| {
×
444
                k == key
×
445
                    && matches!(
×
446
                        &value,
×
447
                        &Value::Array {
448
                            optional: false,
449
                            ..
450
                        }
451
                    )
452
            })
453
        } else {
454
            false
×
455
        }
456
    }
457
}
458

459
impl IsObjectOf<Object> for Value {
460
    fn is_object_of(&self, key: &str) -> bool {
×
461
        if let Value::Object { content, .. } = self {
×
462
            content.iter().any(|(k, value)| {
×
463
                k == key
×
464
                    && matches!(
×
465
                        &value,
×
466
                        &Value::Object {
467
                            optional: false,
468
                            ..
469
                        }
470
                    )
471
            })
472
        } else {
473
            false
×
474
        }
475
    }
476
}
477

478
impl IsObjectOf<OneOf> for Value {
479
    fn is_object_of(&self, key: &str) -> bool {
×
480
        if let Value::Object { content, .. } = self {
×
481
            content.iter().any(|(k, value)| {
×
482
                k == key
×
483
                    && matches!(
×
484
                        &value,
×
485
                        &Value::OneOf {
486
                            optional: false,
487
                            ..
488
                        }
489
                    )
490
            })
491
        } else {
492
            false
×
493
        }
494
    }
495
}
496

497
impl IsObjectOf<Optional<Number>> for Value {
498
    fn is_object_of(&self, key: &str) -> bool {
1✔
499
        if let Value::Object { content, .. } = self {
1✔
500
            content
501
                .iter()
502
                .any(|(k, value)| k == key && matches!(&value, &Value::Number { optional: true }))
3✔
503
        } else {
504
            false
×
505
        }
506
    }
507
}
508

509
impl IsObjectOf<Optional<String>> for Value {
510
    fn is_object_of(&self, key: &str) -> bool {
1✔
511
        if let Value::Object { content, .. } = self {
1✔
512
            content
513
                .iter()
514
                .any(|(k, value)| k == key && matches!(&value, &Value::String { optional: true }))
3✔
515
        } else {
516
            false
×
517
        }
518
    }
519
}
520

521
impl IsObjectOf<Optional<Boolean>> for Value {
522
    fn is_object_of(&self, key: &str) -> bool {
1✔
523
        if let Value::Object { content, .. } = self {
1✔
524
            content
525
                .iter()
526
                .any(|(k, value)| k == key && matches!(&value, &Value::Bool { optional: true }))
3✔
527
        } else {
528
            false
×
529
        }
530
    }
531
}
532

533
impl IsObjectOf<Optional<Array>> for Value {
534
    fn is_object_of(&self, key: &str) -> bool {
×
535
        if let Value::Object { content, .. } = self {
×
536
            content.iter().any(|(k, value)| {
×
537
                k == key && matches!(&value, &Value::Array { optional: true, .. })
×
538
            })
539
        } else {
540
            false
×
541
        }
542
    }
543
}
544

545
impl IsObjectOf<Optional<Object>> for Value {
546
    fn is_object_of(&self, key: &str) -> bool {
×
547
        if let Value::Object { content, .. } = self {
×
548
            content.iter().any(|(k, value)| {
×
549
                k == key && matches!(&value, &Value::Object { optional: true, .. })
×
550
            })
551
        } else {
552
            false
×
553
        }
554
    }
555
}
556

557
impl IsObjectOf<Optional<OneOf>> for Value {
558
    fn is_object_of(&self, key: &str) -> bool {
×
559
        if let Value::Object { content, .. } = self {
×
560
            content.iter().any(|(k, value)| {
×
561
                k == key && matches!(&value, &Value::OneOf { optional: true, .. })
×
562
            })
563
        } else {
564
            false
×
565
        }
566
    }
567
}
568

569
#[cfg(test)]
570
mod tests {
571
    use super::*;
572

573
    #[test]
574
    fn is_array_of_null() {
575
        assert!(IsArrayOf::<Null>::is_array_of(&Value::Array {
576
            r#type: Box::new(Value::Null),
577
            optional: false
578
        }));
579
        assert!(!IsArrayOf::<Null>::is_array_of(&Value::Array {
580
            r#type: Box::new(Value::Number { optional: true }),
581
            optional: false
582
        }));
583
    }
584

585
    #[test]
586
    fn is_array_of_number() {
587
        assert!(IsArrayOf::<Number>::is_array_of(&Value::Array {
588
            r#type: Box::new(Value::Number { optional: false }),
589
            optional: false
590
        }));
591
        assert!(!IsArrayOf::<Number>::is_array_of(&Value::Array {
592
            r#type: Box::new(Value::Bool { optional: true }),
593
            optional: false
594
        }));
595
    }
596

597
    #[test]
598
    fn is_array_of_string() {
599
        assert!(IsArrayOf::<String>::is_array_of(&Value::Array {
600
            r#type: Box::new(Value::String { optional: false }),
601
            optional: false
602
        }));
603
        assert!(!IsArrayOf::<String>::is_array_of(&Value::Array {
604
            r#type: Box::new(Value::Bool { optional: true }),
605
            optional: false
606
        }));
607
    }
608

609
    #[test]
610
    fn is_array_of_bool() {
611
        assert!(IsArrayOf::<Boolean>::is_array_of(&Value::Array {
612
            r#type: Box::new(Value::Bool { optional: false }),
613
            optional: false
614
        }));
615
        assert!(!IsArrayOf::<Boolean>::is_array_of(&Value::Array {
616
            r#type: Box::new(Value::String { optional: true }),
617
            optional: false
618
        }));
619
    }
620

621
    #[test]
622
    fn is_oneof_of_number() {
623
        assert!(IsOneOf::<Optional<Number>>::is_one_of(&Value::OneOf {
624
            variants: [
625
                Value::Number { optional: false },
626
                Value::Bool { optional: false },
627
                Value::String { optional: false },
628
                Value::Null
629
            ]
630
            .into(),
631
            optional: false
632
        }));
633
        assert!(IsOneOf::<Number>::is_one_of(&Value::OneOf {
634
            variants: [
635
                Value::Number { optional: false },
636
                Value::Bool { optional: false },
637
                Value::String { optional: false }
638
            ]
639
            .into(),
640
            optional: false
641
        }));
642
    }
643

644
    #[test]
645
    fn is_oneof_of_bool() {
646
        assert!(IsOneOf::<Optional<Boolean>>::is_one_of(&Value::OneOf {
647
            variants: [
648
                Value::Number { optional: true },
649
                Value::Bool { optional: true },
650
                Value::String { optional: true },
651
                Value::Null
652
            ]
653
            .into(),
654
            optional: false
655
        }));
656
        assert!(IsOneOf::<Boolean>::is_one_of(&Value::OneOf {
657
            variants: [
658
                Value::Number { optional: false },
659
                Value::Bool { optional: false },
660
                Value::String { optional: false }
661
            ]
662
            .into(),
663
            optional: false
664
        }));
665
    }
666

667
    #[test]
668
    fn is_oneof_of_string() {
669
        assert!(IsOneOf::<Optional<String>>::is_one_of(&Value::OneOf {
670
            variants: [
671
                Value::Number { optional: false },
672
                Value::Bool { optional: false },
673
                Value::String { optional: false },
674
                Value::Null
675
            ]
676
            .into(),
677
            optional: false
678
        }));
679
        assert!(IsOneOf::<String>::is_one_of(&Value::OneOf {
680
            variants: [
681
                Value::Number { optional: false },
682
                Value::Bool { optional: false },
683
                Value::String { optional: false }
684
            ]
685
            .into(),
686
            optional: false
687
        }));
688
    }
689

690
    #[test]
691
    fn is_object_of_number() {
692
        assert!(IsObjectOf::<Number>::is_object_of(
693
            &Value::Object {
694
                content: [("key".to_string(), Value::Number { optional: false })].into(),
695
                optional: false
696
            },
697
            "key"
698
        ));
699

700
        assert!(IsObjectOf::<Optional<Number>>::is_object_of(
701
            &Value::Object {
702
                content: [("key".to_string(), Value::Number { optional: true })].into(),
703
                optional: false
704
            },
705
            "key"
706
        ));
707
    }
708

709
    #[test]
710
    fn is_object_of_string() {
711
        assert!(IsObjectOf::<String>::is_object_of(
712
            &Value::Object {
713
                content: [("key".to_string(), Value::String { optional: false })].into(),
714
                optional: false
715
            },
716
            "key"
717
        ));
718

719
        assert!(IsObjectOf::<Optional<String>>::is_object_of(
720
            &Value::Object {
721
                content: [("key".to_string(), Value::String { optional: true })].into(),
722
                optional: false
723
            },
724
            "key"
725
        ));
726
    }
727

728
    #[test]
729
    fn is_object_of_bool() {
730
        assert!(IsObjectOf::<Boolean>::is_object_of(
731
            &Value::Object {
732
                content: [("key".to_string(), Value::Bool { optional: false })].into(),
733
                optional: false
734
            },
735
            "key"
736
        ));
737

738
        assert!(IsObjectOf::<Optional<Boolean>>::is_object_of(
739
            &Value::Object {
740
                content: [("key".to_string(), Value::Bool { optional: true })].into(),
741
                optional: false
742
            },
743
            "key"
744
        ));
745
    }
746
}
747

748
#[cfg(test)]
749
mod ai_tests {
750
    use super::*;
751

752
    #[test]
753
    fn value_is_oneof_number() {
754
        let value = Value::OneOf {
755
            variants: [
756
                Value::Number { optional: false },
757
                Value::String { optional: false },
758
            ]
759
            .into(),
760
            optional: false,
761
        };
762
        assert!(IsOneOf::<Number>::is_one_of(&value));
763
    }
764

765
    #[test]
766
    fn value_is_not_oneof_string() {
767
        let value = Value::OneOf {
768
            variants: [
769
                Value::Number { optional: false },
770
                Value::Bool { optional: false },
771
            ]
772
            .into(),
773
            optional: false,
774
        };
775
        assert!(!IsOneOf::<String>::is_one_of(&value));
776
    }
777

778
    #[test]
779
    fn value_is_oneof_optional_number() {
780
        let value = Value::OneOf {
781
            variants: [Value::Null, Value::Number { optional: false }].into(),
782
            optional: false,
783
        };
784
        assert!(IsOneOf::<Optional<Number>>::is_one_of(&value));
785
    }
786

787
    #[test]
788
    fn value_is_not_oneof_optional_string() {
789
        let value = Value::OneOf {
790
            variants: [
791
                Value::Bool { optional: false },
792
                Value::Number { optional: false },
793
                Value::Null,
794
            ]
795
            .into(),
796
            optional: false,
797
        };
798
        assert!(!IsOneOf::<Optional<String>>::is_one_of(&value));
799
    }
800

801
    #[test]
802
    fn value_is_not_oneof_optional_oneof() {
803
        let value = Value::OneOf {
804
            variants: [
805
                Value::Bool { optional: false },
806
                Value::Number { optional: false },
807
                Value::Null,
808
            ]
809
            .into(),
810
            optional: false,
811
        };
812
        assert!(!IsOneOf::<Optional<OneOf>>::is_one_of(&value));
813
    }
814

815
    #[test]
816
    fn value_is_oneof_optional_oneof() {
817
        let value = Value::OneOf {
818
            variants: [
819
                Value::Bool { optional: false },
820
                Value::Number { optional: false },
821
                Value::Null,
822
            ]
823
            .into(),
824
            optional: true,
825
        };
826
        assert!(IsOneOf::<Optional<OneOf>>::is_one_of(&value));
827
    }
828

829
    #[test]
830
    fn value_is_arrayof_number() {
831
        let value = Value::Array {
832
            r#type: Box::new(Value::Number { optional: false }),
833
            optional: false,
834
        };
835
        assert!(IsArrayOf::<Number>::is_array_of(&value));
836
    }
837

838
    #[test]
839
    fn value_is_not_arrayof_string() {
840
        let value = Value::Array {
841
            r#type: Box::new(Value::Number { optional: false }),
842
            optional: false,
843
        };
844
        assert!(!IsArrayOf::<String>::is_array_of(&value));
845
    }
846

847
    #[test]
848
    fn value_is_arrayof_optional_number() {
849
        let value = Value::Array {
850
            r#type: Box::new(Value::Number { optional: true }),
851
            optional: false,
852
        };
853
        assert!(IsArrayOf::<Optional<Number>>::is_array_of(&value));
854
    }
855

856
    #[test]
857
    fn value_is_not_arrayof_optional_string() {
858
        let value = Value::Array {
859
            r#type: Box::new(Value::Number { optional: true }),
860
            optional: false,
861
        };
862
        assert!(!IsArrayOf::<Optional<String>>::is_array_of(&value));
863
    }
864

865
    #[test]
866
    fn value_is_objectof_number() {
867
        let value = Value::Object {
868
            content: [("key".to_string(), Value::Number { optional: false })].into(),
869
            optional: false,
870
        };
871
        assert!(IsObjectOf::<Number>::is_object_of(&value, "key"));
872
    }
873

874
    #[test]
875
    fn value_is_not_objectof_string() {
876
        let value = Value::Object {
877
            content: [("key".to_string(), Value::Number { optional: false })].into(),
878
            optional: false,
879
        };
880
        assert!(!IsObjectOf::<String>::is_object_of(&value, "key"));
881
    }
882

883
    #[test]
884
    fn test_is_tuple_of_match() {
885
        let value = Value::Tuple {
886
            elements: vec![
887
                Value::Number { optional: false },
888
                Value::String { optional: false },
889
            ],
890
            optional: false,
891
        };
892
        let types = vec![
893
            Value::Number { optional: false },
894
            Value::String { optional: false },
895
        ];
896
        assert!(value.is_tuple_of(&types));
897
    }
898

899
    #[test]
900
    fn test_is_tuple_of_match_with_optional() {
901
        let value = Value::Tuple {
902
            elements: vec![
903
                Value::Number { optional: true },
904
                Value::String { optional: false },
905
            ],
906
            optional: false,
907
        };
908
        let types = vec![
909
            Value::Number { optional: false },
910
            Value::String { optional: false },
911
        ];
912
        assert!(!value.is_tuple_of(&types));
913
    }
914

915
    #[test]
916
    fn test_is_tuple_of_mismatch() {
917
        let value = Value::Tuple {
918
            elements: vec![
919
                Value::Number { optional: false },
920
                Value::String { optional: false },
921
            ],
922
            optional: false,
923
        };
924
        let types = vec![
925
            Value::Number { optional: false },
926
            Value::Bool { optional: false },
927
        ];
928
        assert!(!value.is_tuple_of(&types));
929
    }
930

931
    #[test]
932
    fn test_is_tuple_of_length_mismatch() {
933
        let value = Value::Tuple {
934
            elements: vec![
935
                Value::Number { optional: false },
936
                Value::String { optional: false },
937
            ],
938
            optional: false,
939
        };
940
        let types = vec![Value::Number { optional: false }];
941
        assert!(!value.is_tuple_of(&types));
942
    }
943

944
    #[test]
945
    fn test_is_tuple_of_not_tuple() {
946
        let value = Value::Number { optional: false };
947
        let types = vec![
948
            Value::Number { optional: false },
949
            Value::String { optional: false },
950
        ];
951
        assert!(!value.is_tuple_of(&types));
952
    }
953
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc