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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use crate::{
    bounded::{BoundExt, BoundedGenerator, BoundedValue},
    Driver, TypeGenerator, TypeGeneratorWithParams,
};
use core::{
    cell::{Cell, RefCell, UnsafeCell},
    ops::{Bound, RangeFull},
    sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
        AtomicU64, AtomicU8, AtomicUsize, Ordering,
    },
};

impl TypeGenerator for AtomicBool {
    fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
        Some(AtomicBool::new(driver.gen()?))
    }

    fn mutate<D: Driver>(&mut self, driver: &mut D) -> Option<()> {
        self.store(driver.gen()?, Ordering::SeqCst);
        Some(())
    }
}

macro_rules! impl_atomic_integer {
    ($ty:ident, $inner:ident) => {
        impl TypeGenerator for $ty {
            fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
                Some(Self::new(driver.gen()?))
            }

            fn mutate<D: Driver>(&mut self, driver: &mut D) -> Option<()> {
                self.store(driver.gen()?, Ordering::SeqCst);
                Some(())
            }
        }

        impl BoundedValue for $ty {
            fn gen_bounded<D: Driver>(
                driver: &mut D,
                min: Bound<&Self>,
                max: Bound<&Self>,
            ) -> Option<Self> {
                let min = BoundExt::map(min, |value| value.load(Ordering::SeqCst));
                let max = BoundExt::map(max, |value| value.load(Ordering::SeqCst));

                let value = BoundedValue::gen_bounded(
                    driver,
                    BoundExt::as_ref(&min),
                    BoundExt::as_ref(&max),
                )?;
                Some(Self::new(value))
            }
        }

        impl BoundedValue<$inner> for $ty {
            fn gen_bounded<D: Driver>(
                driver: &mut D,
                min: Bound<&$inner>,
                max: Bound<&$inner>,
            ) -> Option<Self> {
                let value = BoundedValue::gen_bounded(driver, min, max)?;
                Some(Self::new(value))
            }
        }

        impl TypeGeneratorWithParams for $ty {
            type Output = BoundedGenerator<Self, RangeFull>;

            fn gen_with() -> Self::Output {
                BoundedGenerator::new(..)
            }
        }
    };
}

#[test]
fn atomicu8_test() {
    let _ = generator_no_clone_test!(gen::<AtomicU8>());
}

// #[test]
// fn atomicu8_with_test() {
//     let _ = generator_test!(gen::<AtomicU8>()
//         .with()
//         .bounds(AtomicU8::new(0u8)..AtomicU8::new(5)));
// }

impl_atomic_integer!(AtomicI8, i8);
impl_atomic_integer!(AtomicU8, u8);
impl_atomic_integer!(AtomicI16, i16);
impl_atomic_integer!(AtomicU16, u16);
impl_atomic_integer!(AtomicI32, i32);
impl_atomic_integer!(AtomicU32, u32);
impl_atomic_integer!(AtomicI64, i64);
impl_atomic_integer!(AtomicU64, u64);
impl_atomic_integer!(AtomicIsize, isize);
impl_atomic_integer!(AtomicUsize, usize);

impl<T: TypeGenerator> TypeGenerator for Cell<T> {
    fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
        Some(Self::new(driver.gen()?))
    }
}

impl<T: TypeGenerator> TypeGenerator for RefCell<T> {
    fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
        Some(Self::new(driver.gen()?))
    }
}

impl<T: TypeGenerator> TypeGenerator for UnsafeCell<T> {
    fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
        Some(Self::new(driver.gen()?))
    }
}