srt_protocol/options/
units.rs

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        // multiply size to adjust data rate to microseconds (i.e. x 1,000,000)
152        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}