Skip to main content

bolero_generator/any/
default.rs

1use crate::driver::object::{self, DynDriver, Object};
2use core::fmt;
3use std::cell::RefCell;
4
5pub trait Scope: 'static + DynDriver + core::any::Any {
6    fn borrowed(&mut self) -> object::Borrowed;
7}
8
9impl<T> Scope for T
10where
11    T: 'static + DynDriver + core::any::Any,
12{
13    fn borrowed(&mut self) -> object::Borrowed {
14        object::Borrowed(self)
15    }
16}
17
18type Type = Box<dyn Scope>;
19
20thread_local! {
21    static SCOPE: RefCell<Type> = RefCell::new(Box::new(Object(default())));
22}
23
24fn default() -> impl crate::Driver {
25    use rand_core::SeedableRng;
26    use rand_xoshiro::Xoshiro128PlusPlus;
27
28    let mut seed = [42; 16];
29    // make a best effort to get random seeds
30    let _ = getrandom::fill(&mut seed);
31    let rng = Xoshiro128PlusPlus::from_seed(seed);
32    // we don't want to limit the output of this by default for when it hasn't been configured by a fuzzer
33    let config = crate::driver::Options::default()
34        .with_max_len(usize::MAX)
35        .with_max_depth(10);
36    crate::driver::Rng::new(rng, &config)
37}
38
39fn set(value: Type) -> Type {
40    SCOPE.with(|r| core::mem::replace(&mut *r.borrow_mut(), value))
41}
42
43// protect against panics in the `with` function
44struct Prev(Option<Type>);
45
46impl Prev {
47    fn reset(mut self) -> Type {
48        set(self.0.take().unwrap())
49    }
50}
51
52impl Drop for Prev {
53    fn drop(&mut self) {
54        if let Some(prev) = self.0.take() {
55            let _ = set(prev);
56        }
57    }
58}
59
60pub fn with<D, F, R>(driver: Box<D>, f: F) -> (Box<D>, R)
61where
62    D: Scope,
63    F: FnOnce() -> R,
64{
65    let prev = Prev(Some(set(driver)));
66    let res = f();
67    let driver = prev.reset();
68    let driver = if driver.type_id() == core::any::TypeId::of::<D>() {
69        unsafe {
70            let raw = Box::into_raw(driver);
71            Box::from_raw(raw as *mut D)
72        }
73    } else {
74        panic!(
75            "invalid scope state; expected {}",
76            core::any::type_name::<D>()
77        )
78    };
79    (driver, res)
80}
81
82fn borrow_with<F: FnOnce(&mut object::Borrowed) -> R, R>(f: F) -> R {
83    SCOPE.with(|r| {
84        let mut driver = r.borrow_mut();
85        let mut driver = driver.borrowed();
86        f(&mut driver)
87    })
88}
89
90#[track_caller]
91pub fn any<G: crate::ValueGenerator>(g: &G) -> G::Output {
92    borrow_with(|driver| {
93        g.generate(driver).unwrap_or_else(|| {
94            std::panic::panic_any(Error {
95                location: core::panic::Location::caller(),
96                generator: core::any::type_name::<G>(),
97                output: core::any::type_name::<G::Output>(),
98            })
99        })
100    })
101}
102
103#[track_caller]
104pub fn assume(condition: bool, message: &'static str) {
105    if !condition {
106        std::panic::panic_any(Error {
107            location: core::panic::Location::caller(),
108            generator: "<assume>",
109            output: message,
110        });
111    }
112}
113
114#[track_caller]
115pub fn fill_bytes(bytes: &mut [u8]) {
116    borrow_with(|driver| {
117        let len = bytes.len();
118        let mut hint = || (len, Some(len));
119        driver
120            .0
121            .gen_from_bytes(&mut hint, &mut |src: &[u8]| {
122                if src.len() == len {
123                    bytes.copy_from_slice(src);
124                    Some(len)
125                } else {
126                    None
127                }
128            })
129            .unwrap_or_else(|| {
130                std::panic::panic_any(Error {
131                    location: core::panic::Location::caller(),
132                    generator: "<fill_bytes>",
133                    output: "could not generate enough bytes",
134                });
135            })
136    })
137}
138
139#[derive(Clone)]
140pub struct Error {
141    location: &'static core::panic::Location<'static>,
142    generator: &'static str,
143    output: &'static str,
144}
145
146impl fmt::Debug for Error {
147    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148        f.debug_struct("Error")
149            .field("location", &self.location)
150            .field("generator", &self.generator)
151            .field("output", &self.output)
152            .finish()
153    }
154}
155
156impl fmt::Display for Error {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        write!(
159            f,
160            "Could not generate value of type {} at {}",
161            self.output, self.location,
162        )
163    }
164}
165
166impl std::error::Error for Error {}