1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use std::collections::HashMap;
use std::ops::Range;

use serde_json::{Map, Number, Value};

use crate::{Dummy, Fake, Faker};

const JSON_UNION_MEMBERS_NON_RECURSIVE: Range<usize> = 0..4;
const JSON_UNION_MEMBERS: Range<usize> = 0..6;

// The Mapping cant include arrays or mappings
// to avoid overflowing the stack.
struct NonRecursiveValue(Value);

impl Dummy<Faker> for NonRecursiveValue {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &Faker, rng: &mut R) -> Self {
        let union_index: usize = JSON_UNION_MEMBERS_NON_RECURSIVE.fake_with_rng(rng);
        match union_index {
            0 => NonRecursiveValue(serde_json::Value::Null),
            1 => NonRecursiveValue(serde_json::Value::Bool(config.fake_with_rng(rng))),
            2 => NonRecursiveValue(serde_json::Value::Number(config.fake_with_rng(rng))),
            3 => NonRecursiveValue(serde_json::Value::String(config.fake_with_rng(rng))),
            _ => panic!(),
        }
    }
}

impl Dummy<Faker> for Value {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &Faker, rng: &mut R) -> Self {
        let union_index: usize = JSON_UNION_MEMBERS.fake_with_rng(rng);
        match union_index {
            0 => serde_json::Value::Null,
            1 => serde_json::Value::Bool(config.fake_with_rng(rng)),
            2 => serde_json::Value::Number(config.fake_with_rng(rng)),
            3 => serde_json::Value::String(config.fake_with_rng(rng)),
            4 => serde_json::Value::Array(config.fake_with_rng(rng)),
            5 => serde_json::Value::Object(config.fake_with_rng(rng)),
            _ => panic!(),
        }
    }
}

impl Dummy<Faker> for Number {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &Faker, rng: &mut R) -> Self {
        // Alternate between generating floats and integers
        if Faker.fake_with_rng::<bool, _>(rng) {
            Number::from_f64(config.fake_with_rng::<f64, _>(rng)).unwrap()
        } else {
            Number::from_f64(config.fake_with_rng::<i32, _>(rng).into()).unwrap()
        }
    }
}

impl Dummy<Faker> for Map<String, Value> {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &Faker, rng: &mut R) -> Self {
        Map::from_iter(
            config
                .fake_with_rng::<HashMap<String, NonRecursiveValue>, _>(rng)
                .iter()
                .map(|(x, y)| (x.to_owned(), y.0.to_owned())),
        )
    }
}