1use std::{
2 ops::{Div, Mul},
3 time::Duration,
4};
5
6use derive_more::*;
7
8#[derive(Debug, Deref, Display, Into, Mul, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
9#[display(fmt = "{_0} bytes")]
10pub struct ByteCount(pub u64);
11
12impl From<ByteCount> for usize {
13 fn from(value: ByteCount) -> Self {
14 value.0 as usize
15 }
16}
17
18impl Div<PacketSize> for ByteCount {
19 type Output = PacketCount;
20
21 fn div(self, rhs: PacketSize) -> Self::Output {
22 PacketCount(self.0 / rhs.0)
23 }
24}
25
26#[derive(Debug, Deref, Display, Into, Add, Sub, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
27#[display(fmt = "{_0} bytes")]
28pub struct PacketSize(pub u64);
29
30impl From<PacketSize> for usize {
31 fn from(value: PacketSize) -> Self {
32 value.0 as usize
33 }
34}
35
36#[derive(Debug, Deref, Display, Into, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
37#[display(fmt = "{_0} packets")]
38pub struct PacketCount(pub u64);
39
40impl From<PacketCount> for usize {
41 fn from(value: PacketCount) -> Self {
42 value.0 as usize
43 }
44}
45
46impl Mul<PacketCount> for PacketSize {
47 type Output = ByteCount;
48
49 fn mul(self, rhs: PacketCount) -> Self::Output {
50 ByteCount(self.0 * rhs.0)
51 }
52}
53
54impl Mul<PacketSize> for PacketCount {
55 type Output = ByteCount;
56
57 fn mul(self, rhs: PacketSize) -> Self::Output {
58 rhs * self
59 }
60}
61
62impl PacketCount {
63 pub fn for_time_window(window: Duration, packet_spacing: Duration) -> PacketCount {
64 PacketCount((window.as_micros() / packet_spacing.as_micros()) as u64)
65 }
66}
67
68#[derive(Debug, Deref, Display, Into, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
69#[display(fmt = "{_0} bytes/s")]
70pub struct DataRate(pub u64);
71
72impl Mul<Duration> for DataRate {
73 type Output = ByteCount;
74
75 fn mul(self, rhs: Duration) -> Self::Output {
76 let bytes_nearest_second = self.0 * rhs.as_secs();
77 let bytes_scaled_for_micros = self.0.saturating_mul(u64::from(rhs.subsec_micros()));
78 let bytes_remaining_micros = bytes_scaled_for_micros / 1_000_000;
79 ByteCount(bytes_nearest_second + bytes_remaining_micros)
80 }
81}
82
83impl Mul<DataRate> for Duration {
84 type Output = ByteCount;
85
86 fn mul(self, rhs: DataRate) -> Self::Output {
87 rhs * self
88 }
89}
90
91impl DataRate {
92 pub fn as_mbps_f64(&self) -> f64 {
93 self.0 as f64 / 1_000_000.
94 }
95}
96
97#[derive(Debug, Deref, Display, Into, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
98#[display(fmt = "{_0} packets/s")]
99pub struct PacketRate(pub u64);
100
101impl Mul<Duration> for PacketRate {
102 type Output = PacketCount;
103
104 fn mul(self, rhs: Duration) -> Self::Output {
105 let packets_nearest_second = self.0 * rhs.as_secs();
106 let packets_scaled_for_micros =
107 (self.0 as usize).saturating_mul(rhs.subsec_micros() as usize);
108 let packets_remaining_micros = (packets_scaled_for_micros / 1_000_000) as u64;
109 PacketCount(packets_nearest_second + packets_remaining_micros)
110 }
111}
112
113impl Mul<PacketRate> for Duration {
114 type Output = PacketCount;
115
116 fn mul(self, rhs: PacketRate) -> Self::Output {
117 rhs * self
118 }
119}
120
121impl Div<PacketRate> for DataRate {
122 type Output = PacketSize;
123
124 fn div(self, rhs: PacketRate) -> Self::Output {
125 PacketSize(self.0 / rhs.0)
126 }
127}
128
129#[derive(Debug, Deref, Display, Into, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
130#[display(fmt = "{} s/p", "_0.as_secs_f64()")]
131pub struct PacketPeriod(pub Duration);
132
133impl Mul<PacketCount> for PacketPeriod {
134 type Output = Duration;
135
136 fn mul(self, rhs: PacketCount) -> Self::Output {
137 self.0 * rhs.0 as u32
138 }
139}
140
141impl Mul<PacketPeriod> for PacketCount {
142 type Output = Duration;
143
144 fn mul(self, rhs: PacketPeriod) -> Self::Output {
145 rhs * self
146 }
147}
148
149impl PacketPeriod {
150 pub fn try_from(data_rate: DataRate, packet_size: PacketSize) -> Option<Duration> {
151 if packet_size.0 > 0 {
153 let period = packet_size.0 * 1_000_000 / data_rate.0;
154 if period > 0 {
155 return Some(Duration::from_micros(period));
156 }
157 }
158 None
159 }
160}
161
162#[derive(Debug, Deref, Display, Into, Add, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
163#[display(fmt = "{_0}%")]
164pub struct Percent(pub u64);
165
166impl Mul<DataRate> for Percent {
167 type Output = DataRate;
168
169 fn mul(self, rhs: DataRate) -> Self::Output {
170 DataRate(self.0 * rhs.0 / 100)
171 }
172}
173
174impl Mul<Percent> for DataRate {
175 type Output = DataRate;
176
177 fn mul(self, rhs: Percent) -> Self::Output {
178 rhs * self
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185
186 #[test]
187 fn data_rate_and_duration_multiplication() {
188 let data_rate = DataRate(1_000_000);
189 let period = Duration::from_millis(1);
190
191 let bytes = data_rate * period;
192
193 assert_eq!(bytes, ByteCount(1_000))
194 }
195
196 #[test]
197 fn packet_rate_and_duration_multiplication() {
198 let packet_rate = PacketRate(1_000_000);
199 let period = Duration::from_millis(1);
200
201 let packets = packet_rate * period;
202
203 assert_eq!(packets, PacketCount(1_000))
204 }
205
206 #[test]
207 fn packet_period_from_data_rate_and_packet_size() {
208 let data_rate = DataRate(20_000);
209 let packet_size = PacketSize(500);
210
211 let period = PacketPeriod::try_from(data_rate, packet_size);
212
213 assert_eq!(period, Some(Duration::from_millis(25)))
214 }
215
216 #[test]
217 fn display() {
218 assert_eq!(format!("{}", ByteCount(100)), "100 bytes");
219 assert_eq!(format!("{}", PacketSize(100)), "100 bytes");
220 assert_eq!(format!("{}", PacketCount(100)), "100 packets");
221 assert_eq!(format!("{}", DataRate(100)), "100 bytes/s");
222 assert_eq!(format!("{}", PacketRate(100)), "100 packets/s");
223 assert_eq!(format!("{}", Percent(100)), "100%");
224 }
225}