bitbelay_providers/
numeric.rs

1//! Numeric data providers.
2
3use rand::rngs::ThreadRng;
4use rand::Rng as _;
5
6/// A `u64` data provider.
7///
8///
9/// # Notes
10///
11/// * `u64` are always stored in an **little endian** fashion to avoid any
12///   variances due to platform storage conventions.
13#[derive(Debug, Default)]
14pub struct Unsigned64BitProvider {
15    /// The name.
16    name: String,
17
18    /// The number of `u64`s to provide per call.
19    length: usize,
20
21    /// The current data stored in the provider.
22    data: Vec<Vec<u8>>,
23
24    /// A thread-local random generator.
25    rng: ThreadRng,
26}
27
28impl Unsigned64BitProvider {
29    /// Creates a new `u64` data provider that returns `length` 64-bit unsigned
30    /// integers (stored in a little endian representation).
31    ///
32    /// # Examples
33    ///
34    /// ```
35    /// use bitbelay_providers::numeric::Unsigned64BitProvider;
36    /// // The trait must also be in scope to access the `provide()` method.
37    /// use bitbelay_providers::Provider as _;
38    ///
39    /// let mut provider = Unsigned64BitProvider::new(10);
40    ///
41    /// let data = provider.provide(20);
42    /// assert_eq!(data.len(), 20);
43    /// // Note that each u64 is eight (8) bytes, so we can expect a length
44    /// // of `10 * 8 = 80`.
45    /// assert_eq!(data.first().unwrap().len(), 80);
46    /// ```
47    pub fn new(length: usize) -> Self {
48        Self {
49            name: format!("Unsigned 64-bit integers (n={})", length),
50            length,
51            data: Vec::with_capacity(length),
52            rng: rand::thread_rng(),
53        }
54    }
55}
56
57impl crate::Provider for Unsigned64BitProvider {
58    fn name(&self) -> &str {
59        self.name.as_str()
60    }
61
62    fn provide(&mut self, n: usize) -> Vec<&[u8]> {
63        self.data.clear();
64
65        for _ in 0..n {
66            let mut buffer = Vec::with_capacity(self.length);
67            for _ in 0..self.length {
68                let random_value = self.rng.gen::<u64>();
69                buffer.extend_from_slice(&random_value.to_le_bytes());
70            }
71            self.data.push(buffer);
72        }
73
74        self.data.iter().map(|x| x.as_slice()).collect::<Vec<_>>()
75    }
76
77    fn bytes_per_input(&mut self) -> usize {
78        std::mem::size_of::<u64>() * self.length
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85    use crate::Provider;
86
87    #[test]
88    fn it_correctly_calculates_bytes_per_input() {
89        let mut provider = Unsigned64BitProvider::new(10);
90        // SAFETY: we provided one input, so the direct index to `0` will always
91        // succeed.
92        let data = provider.provide(1)[0];
93        assert_eq!(data.len(), provider.bytes_per_input());
94    }
95}