1use rand::Rng;
4
5use super::{ConfigSource, memory::ConfigSourceBuilder};
6use crate::{ConfigError, ConfigValue, value::RandValue};
7
8#[allow(missing_debug_implementations, missing_copy_implementations)]
10pub(crate) struct Random;
11
12impl ConfigSource for Random {
13 fn name(&self) -> &str {
14 "random_generator"
15 }
16
17 fn load(&self, source: &mut ConfigSourceBuilder<'_>) -> Result<(), ConfigError> {
18 source.set("random.u8", RandValue::U8);
19 source.set("random.u16", RandValue::U16);
20 source.set("random.u32", RandValue::U32);
21 source.set("random.u64", RandValue::U64);
22 source.set("random.u128", RandValue::U128);
23 source.set("random.usize", RandValue::Usize);
24 source.set("random.i8", RandValue::I8);
25 source.set("random.i16", RandValue::I16);
26 source.set("random.i32", RandValue::I32);
27 source.set("random.i64", RandValue::I64);
28 source.set("random.i128", RandValue::I128);
29 source.set("random.isize", RandValue::Isize);
30 Ok(())
31 }
32}
33
34macro_rules! get_val {
35 ($($f:ident.$n:literal),+) => {$(
36 #[inline]
37 fn $f<R, F: Fn(&[u8; $n]) -> R>(f: F) -> R {
38 let mut rng = rand::rng();
39 let mut x = [0; $n];
40 rng.fill_bytes(&mut x);
41 (f)(&x)
42 }
43 )+};
44}
45
46get_val!(get_1.1, get_2.2, get_4.4, get_8.8, get_16.16);
47
48impl RandValue {
49 pub(crate) fn normalize(self) -> ConfigValue<'static> {
50 match self {
51 RandValue::U8 => get_1(|f| u8::from_le_bytes(*f)).into(),
52 RandValue::U16 => get_2(|f| u16::from_le_bytes(*f)).into(),
53 RandValue::U32 => get_4(|f| u32::from_le_bytes(*f)).into(),
54 RandValue::U64 => get_8(|f| u64::from_le_bytes(*f)).into(),
55 RandValue::U128 => get_16(|f| u128::from_le_bytes(*f)).into(),
56 #[cfg(target_pointer_width = "64")]
57 RandValue::Usize => get_8(|f| usize::from_le_bytes(*f)).into(),
58 #[cfg(target_pointer_width = "32")]
59 RandValue::Usize => get_4(|f| usize::from_le_bytes(*f)).into(),
60 RandValue::I8 => get_1(|f| i8::from_le_bytes(*f)).into(),
61 RandValue::I16 => get_2(|f| i16::from_le_bytes(*f)).into(),
62 RandValue::I32 => get_4(|f| i32::from_le_bytes(*f)).into(),
63 RandValue::I64 => get_8(|f| i64::from_le_bytes(*f)).into(),
64 RandValue::I128 => get_16(|f| i128::from_le_bytes(*f)).into(),
65 #[cfg(target_pointer_width = "64")]
66 RandValue::Isize => get_8(|f| isize::from_le_bytes(*f)).into(),
67 #[cfg(target_pointer_width = "32")]
68 RandValue::Isize => get_4(|f| isize::from_le_bytes(*f)).into(),
69 }
70 }
71}
72
73#[cfg_attr(coverage_nightly, coverage(off))]
74#[cfg(test)]
75mod test {
76
77 use crate::test::TestConfigExt;
78
79 use super::Random;
80
81 #[test]
82 fn env_test() {
83 let config = Random.new_config();
84 let a = config.get::<u128>("random.u128").unwrap();
85 let b = config.get::<u128>("random.u128").unwrap();
86 assert_ne!(a, b);
87 }
88
89 #[test]
90 fn value_test() {
91 let config = Random.new_config();
92 assert!(config.get::<u8>("random.u8").is_ok());
93 assert!(config.get::<u16>("random.u16").is_ok());
94 assert!(config.get::<u32>("random.u32").is_ok());
95 assert!(config.get::<u64>("random.u64").is_ok());
96 assert!(config.get::<u128>("random.u128").is_ok());
97 assert!(config.get::<usize>("random.usize").is_ok());
98 assert!(config.get::<i8>("random.i8").is_ok());
99 assert!(config.get::<i16>("random.i16").is_ok());
100 assert!(config.get::<i32>("random.i32").is_ok());
101 assert!(config.get::<i64>("random.i64").is_ok());
102 assert!(config.get::<i128>("random.i128").is_ok());
103 assert!(config.get::<isize>("random.isize").is_ok());
104 }
105}