sphinx_packet/header/
delays.rs1use crate::constants::DELAY_LENGTH;
16use byteorder::{BigEndian, ByteOrder};
17use rand_distr::num_traits::Zero;
18use rand_distr::{Distribution, Exp};
19use std::{borrow::Borrow, time::Duration};
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct Delay(u64);
25
26impl Delay {
27 pub const fn new_from_nanos(value: u64) -> Self {
29 Delay(value)
30 }
31
32 pub const fn new_from_millis(value: u64) -> Self {
33 const NANOS_PER_MILLI: u64 = 1_000_000;
34
35 Self::new_from_nanos(NANOS_PER_MILLI * value)
36 }
37
38 pub fn to_nanos(&self) -> u64 {
39 self.0
40 }
41
42 pub fn to_duration(&self) -> Duration {
43 Duration::from_nanos(self.0)
44 }
45
46 pub fn to_bytes(&self) -> [u8; DELAY_LENGTH] {
47 let mut delay_bytes = [0; DELAY_LENGTH];
48 BigEndian::write_u64(&mut delay_bytes, self.0);
49 delay_bytes
50 }
51
52 pub fn from_bytes(delay_bytes: [u8; DELAY_LENGTH]) -> Self {
53 Delay(BigEndian::read_u64(&delay_bytes))
54 }
55}
56
57impl<T> std::iter::Sum<T> for Delay
58where
59 T: Borrow<Delay>,
60{
61 fn sum<I>(iter: I) -> Self
62 where
63 I: Iterator<Item = T>,
64 {
65 iter.fold(Delay(0), |acc, item| acc + item)
66 }
67}
68
69impl<T> std::ops::Add<T> for &Delay
70where
71 T: Borrow<Delay>,
72{
73 type Output = Delay;
74 fn add(self, rhs: T) -> Self::Output {
75 *self + rhs
76 }
77}
78
79impl<T> std::ops::Add<T> for Delay
80where
81 T: Borrow<Delay>,
82{
83 type Output = Delay;
84 fn add(self, rhs: T) -> Self::Output {
85 Delay(self.0 + rhs.borrow().0)
86 }
87}
88
89impl std::ops::Mul<f64> for Delay {
90 type Output = Delay;
91 fn mul(self, rhs: f64) -> Self::Output {
92 Delay((self.0 as f64 * rhs) as u64)
99 }
100}
101
102pub fn generate_from_nanos(number: usize, average_delay: u64) -> Vec<Delay> {
106 generate_delays(number, average_delay as f64)
107}
108
109pub fn generate_from_average_duration(number: usize, average_delay: Duration) -> Vec<Delay> {
110 generate_delays(number, average_delay.as_nanos() as f64)
111}
112
113fn generate_delays(number: usize, average_delay: f64) -> Vec<Delay> {
114 if average_delay.is_zero() {
115 return vec![Delay::new_from_nanos(0); number];
116 }
117
118 let Ok(exp) = Exp::new(1.0 / average_delay) else {
119 return vec![Delay::new_from_nanos(0); number];
120 };
121
122 let mut delays = Vec::new();
123 for _ in 0..number {
124 delays.push(Delay::new_from_nanos(
126 exp.sample(&mut rand::thread_rng()).round() as u64,
127 ));
128 }
129 delays
130}
131
132#[cfg(test)]
133mod test_delay_generation {
134 use super::*;
135
136 #[test]
137 fn with_0_delays_returns_an_empty_vector() {
138 let delays = generate_from_average_duration(0, Duration::from_millis(10));
139 assert_eq!(0, delays.len());
140 }
141
142 #[test]
143 fn with_1_delay_it_returns_1_delay() {
144 let delays = generate_from_average_duration(1, Duration::from_secs(1));
145 assert_eq!(1, delays.len());
146 }
147
148 #[test]
149 fn with_3_delays_it_returns_3_delays() {
150 let delays = generate_from_average_duration(3, Duration::from_nanos(1));
151 assert_eq!(3, delays.len());
152 }
153
154 #[test]
155 fn it_is_possible_to_convert_it_to_and_from_bytes_without_data_loss() {
156 let expected_delay_nanos = 1_234_567_890; let delay = Delay::new_from_nanos(expected_delay_nanos);
158 let delay_bytes = delay.to_bytes();
159 let recovered_delay = Delay::from_bytes(delay_bytes);
160 assert_eq!(delay, recovered_delay);
161 }
162
163 #[test]
164 fn it_is_possible_to_convert_it_to_and_from_nanos_without_data_loss() {
165 let expected_delay_nanos = 1_234_567_890; let delay = Delay::new_from_nanos(expected_delay_nanos);
167 assert_eq!(expected_delay_nanos, delay.to_nanos());
168 }
169
170 #[test]
171 fn it_is_possible_to_convert_it_to_and_from_duration_without_data_loss() {
172 let expected_delay_nanos = 1_234_567_890; let delay = Delay::new_from_nanos(expected_delay_nanos);
174 let delay_duration = delay.to_duration();
175 assert_eq!(Duration::from_nanos(expected_delay_nanos), delay_duration);
176 }
177}
178
179#[cfg(test)]
180mod delay_summing {
181 use super::*;
182
183 #[test]
184 fn works_with_std_ops_only() {
185 let delay1 = Delay(42);
186 let delay2 = Delay(123);
187
188 let expected1 = Delay(165);
189 assert_eq!(expected1, delay1 + delay2);
190
191 let expected2 = Delay(265);
192 let delay3 = Delay(100);
193 assert_eq!(expected2, delay1 + delay2 + delay3)
194 }
195
196 #[test]
197 fn works_with_iterator() {
198 let delays = [Delay(42), Delay(123), Delay(100)];
199 let expected = Delay(265);
200
201 assert_eq!(expected, delays.iter().sum());
202 assert_eq!(Delay(0), Vec::new().iter().sum())
203 }
204}