net_bytes/
download_speed.rs1use std::time::Duration;
2
3use crate::{FileSizeFormat, format_parts_scaled, SCALE};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
13pub struct DownloadSpeed {
14 scaled_bps: u128,
16}
17
18impl DownloadSpeed {
19 #[inline]
29 pub fn from_raw(bytes_per_second: u64) -> Self {
30 Self {
31 scaled_bps: (bytes_per_second as u128) * SCALE,
32 }
33 }
34
35 pub fn new(bytes: u64, duration: Duration) -> Self {
51 let nanos = duration.as_nanos();
52 if nanos == 0 {
53 return Self { scaled_bps: 0 };
54 }
55
56 let scaled_bps = (bytes as u128) * SCALE * 1_000_000_000 / nanos;
63
64 Self { scaled_bps }
65 }
66
67 #[inline]
71 pub fn as_scaled(&self) -> u128 {
72 self.scaled_bps
73 }
74
75 #[inline]
79 pub fn as_u64(&self) -> u64 {
80 (self.scaled_bps / SCALE) as u64
81 }
82
83 #[inline]
87 pub fn as_f64(&self) -> f64 {
88 self.scaled_bps as f64 / SCALE as f64
89 }
90}
91
92impl FileSizeFormat for DownloadSpeed {
93 fn get_si_parts(&self) -> (String, &'static str) {
97 const UNITS: &[&str] = &[
98 "B/s", "KB/s", "MB/s", "GB/s", "TB/s", "PB/s", "EB/s", "ZB/s", "YB/s",
99 ];
100 format_parts_scaled(self.scaled_bps, 1000, UNITS)
101 }
102
103 fn get_iec_parts(&self) -> (String, &'static str) {
107 const UNITS: &[&str] = &[
108 "B/s", "KiB/s", "MiB/s", "GiB/s", "TiB/s", "PiB/s", "EiB/s", "ZiB/s", "YiB/s",
109 ];
110 format_parts_scaled(self.scaled_bps, 1024, UNITS)
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use std::time::Duration;
117
118 use super::DownloadSpeed;
119 use crate::{SizeStandard, FileSizeFormat};
120
121 fn format_test_si(bytes: u64) -> String {
125 DownloadSpeed::from_raw(bytes).to_formatted(SizeStandard::SI).to_string()
126 }
127
128 fn format_test_iec(bytes: u64) -> String {
132 DownloadSpeed::from_raw(bytes).to_formatted(SizeStandard::IEC).to_string()
133 }
134
135 #[test]
138 fn test_si_speed() {
139 assert_eq!(format_test_si(512), "512.0 B/s");
140 assert_eq!(format_test_si(1000), "1.00 KB/s");
141 assert_eq!(format_test_si(1024), "1.02 KB/s");
142 assert_eq!(format_test_si(9999), "10.00 KB/s");
143 assert_eq!(format_test_si(10_000), "10.0 KB/s");
144 assert_eq!(format_test_si(100_000), "100.0 KB/s");
145 }
146
147 #[test]
150 fn test_iec_speed() {
151 assert_eq!(format_test_iec(0), "0.00 B/s");
152 assert_eq!(format_test_iec(1024), "1.00 KiB/s");
153 assert_eq!(format_test_iec(1500), "1.46 KiB/s");
154
155 let bytes_near_10 = (9.999 * 1024.0) as u64;
156 assert_eq!(format_test_iec(bytes_near_10), "10.00 KiB/s");
157
158 assert_eq!(format_test_iec(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format_test_iec(100 * 1024), "100.0 KiB/s");
160 }
161
162 #[test]
163 fn test_zero_speed() {
164 let zero_speed = DownloadSpeed::from_raw(0);
165 assert_eq!(zero_speed.as_u64(), 0);
166 assert_eq!(zero_speed.as_scaled(), 0);
167
168 let formatted = zero_speed.to_formatted(SizeStandard::SI).to_string();
169 assert_eq!(formatted, "0.00 B/s");
170
171 let zero_duration = Duration::from_secs(0);
172 let zero_speed = DownloadSpeed::new(1000, zero_duration);
173 assert_eq!(zero_speed.as_u64(), 0);
174 }
175
176 #[test]
179 fn test_new_basic() {
180 let speed = DownloadSpeed::new(1000, Duration::from_secs(1));
182 assert_eq!(speed.as_u64(), 1000);
183
184 let speed = DownloadSpeed::new(2000, Duration::from_secs(2));
186 assert_eq!(speed.as_u64(), 1000);
187
188 let speed = DownloadSpeed::new(1000, Duration::from_millis(500));
190 assert_eq!(speed.as_u64(), 2000);
191 }
192
193 #[test]
194 fn test_new_with_subsec_nanos() {
195 let speed = DownloadSpeed::new(1000, Duration::from_millis(1500));
197 assert_eq!(speed.as_u64(), 666);
198
199 let speed = DownloadSpeed::new(1000, Duration::from_millis(100));
201 assert_eq!(speed.as_u64(), 10000);
202
203 let speed = DownloadSpeed::new(1_000_000, Duration::new(1, 1));
205 assert!(speed.as_u64() >= 999_999); }
207
208 #[test]
209 fn test_new_zero_bytes() {
210 let speed = DownloadSpeed::new(0, Duration::from_secs(10));
212 assert_eq!(speed.as_u64(), 0);
213 assert_eq!(speed.as_scaled(), 0);
214 }
215
216 #[test]
217 fn test_new_zero_duration() {
218 let speed = DownloadSpeed::new(1000, Duration::ZERO);
220 assert_eq!(speed.as_u64(), 0);
221 assert_eq!(speed.as_scaled(), 0);
222 }
223
224 #[test]
225 fn test_new_large_values() {
226 let speed = DownloadSpeed::new(1_000_000_000, Duration::from_secs(1));
228 assert_eq!(speed.as_u64(), 1_000_000_000);
229
230 let speed = DownloadSpeed::new(10_000_000_000, Duration::from_secs(10));
232 assert_eq!(speed.as_u64(), 1_000_000_000);
233 }
234
235 #[test]
236 fn test_new_extreme_values() {
237 let speed = DownloadSpeed::new(1, Duration::from_secs(1));
239 assert_eq!(speed.as_u64(), 1);
240
241 let speed = DownloadSpeed::new(1, Duration::from_secs(100 * 365 * 24 * 60 * 60));
243 assert_eq!(speed.as_u64(), 0);
244 }
245
246 #[test]
247 fn test_new_edge_cases() {
248 let speed = DownloadSpeed::new(1, Duration::from_nanos(1));
250 assert_eq!(speed.as_u64(), 1_000_000_000);
251
252 let speed = DownloadSpeed::new(1, Duration::from_secs(1));
254 assert_eq!(speed.as_u64(), 1);
255 }
256}