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}