1use std::{error::Error as StdError, fmt, str::Chars};
15
16#[cfg(feature = "binary-system")]
17pub mod binary_system;
18#[cfg(feature = "serde")]
19pub mod option;
20#[cfg(feature = "serde")]
21pub mod serde;
22
23pub mod re {
25 pub use bandwidth;
26}
27
28use bandwidth::Bandwidth;
29
30const FRACTION_PART_LIMIT: u32 = 12;
31
32#[derive(Debug, PartialEq, Clone)]
34pub enum Error {
35 InvalidCharacter(usize),
41 NumberExpected(usize),
50 UnknownUnit {
58 start: usize,
60 end: usize,
62 unit: String,
64 value: u64,
66 },
67 #[cfg(feature = "binary-system")]
68 UnknownBinaryUnit {
76 start: usize,
78 end: usize,
80 unit: String,
82 value: u64,
84 },
85 NumberOverflow,
89 Empty,
91}
92
93impl StdError for Error {}
94
95impl fmt::Display for Error {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 match self {
98 Error::InvalidCharacter(offset) => write!(f, "invalid character at {}", offset),
99 Error::NumberExpected(offset) => write!(f, "expected number at {}", offset),
100 Error::UnknownUnit { unit, value, .. } if unit.is_empty() => {
101 write!(
102 f,
103 "bandwidth unit needed, for example {0}Mbps or {0}bps",
104 value,
105 )
106 }
107 Error::UnknownUnit { unit, .. } => {
108 write!(
109 f,
110 "unknown bandwidth unit {:?}, \
111 supported units: bps, kbps, Mbps, Gbps, Tbps",
112 unit
113 )
114 }
115 #[cfg(feature = "binary-system")]
116 Error::UnknownBinaryUnit { unit, value, .. } if unit.is_empty() => {
117 write!(
118 f,
119 "binary bandwidth unit needed, for example {0}MiB/s or {0}B/s",
120 value,
121 )
122 }
123 #[cfg(feature = "binary-system")]
124 Error::UnknownBinaryUnit { unit, .. } => {
125 write!(
126 f,
127 "unknown binary bandwidth unit {:?}, \
128 supported units: B/s, kiB/s, MiB/s, GiB/s, TiB/s",
129 unit
130 )
131 }
132 Error::NumberOverflow => write!(f, "number is too large"),
133 Error::Empty => write!(f, "value was empty"),
134 }
135 }
136}
137
138#[derive(Debug, Clone)]
140pub struct FormattedBandwidth(Bandwidth);
141
142trait OverflowOp: Sized {
143 fn mul(self, other: Self) -> Result<Self, Error>;
144 fn add(self, other: Self) -> Result<Self, Error>;
145}
146
147impl OverflowOp for u64 {
148 fn mul(self, other: Self) -> Result<Self, Error> {
149 self.checked_mul(other).ok_or(Error::NumberOverflow)
150 }
151 fn add(self, other: Self) -> Result<Self, Error> {
152 self.checked_add(other).ok_or(Error::NumberOverflow)
153 }
154}
155
156fn parse_fraction(fraction: u64, fraction_cnt: u32, need_digit: u32) -> u64 {
157 if need_digit >= fraction_cnt {
158 fraction * 10u64.pow(need_digit - fraction_cnt)
159 } else {
160 fraction / 10u64.pow(fraction_cnt - need_digit)
161 }
162}
163
164struct Parser<'a> {
165 iter: Chars<'a>,
166 src: &'a str,
167 current: Bandwidth,
168}
169
170impl<'a> Parser<'a> {
171 fn new<'b: 'a>(s: &'b str) -> Self {
172 Parser {
173 iter: s.chars(),
174 src: s,
175 current: Bandwidth::new(0, 0),
176 }
177 }
178}
179
180impl Parser<'_> {
181 fn off(&self) -> usize {
182 self.src.len() - self.iter.as_str().len()
183 }
184
185 fn parse_first_char(&mut self) -> Result<Option<u64>, Error> {
186 let off = self.off();
187 for c in self.iter.by_ref() {
188 match c {
189 '0'..='9' => {
190 return Ok(Some(c as u64 - '0' as u64));
191 }
192 c if c.is_whitespace() => continue,
193 _ => {
194 return Err(Error::NumberExpected(off));
195 }
196 }
197 }
198 Ok(None)
199 }
200
201 fn parse_unit(
202 &mut self,
203 n: u64,
204 fraction: u64,
205 fraction_cnt: u32,
206 start: usize,
207 end: usize,
208 ) -> Result<(), Error> {
209 let (gbps, bps) = match &self.src[start..end] {
210 "bps" | "bit/s" | "b/s" => (0u64, n),
211 "kbps" | "Kbps" | "kbit/s" | "Kbit/s" | "kb/s" | "Kb/s" => (
212 0u64,
213 n.mul(1000)?
214 .add(parse_fraction(fraction, fraction_cnt, 3))?,
215 ),
216 "Mbps" | "mbps" | "Mbit/s" | "mbit/s" | "Mb/s" | "mb/s" => (
217 0u64,
218 n.mul(1_000_000)?
219 .add(parse_fraction(fraction, fraction_cnt, 6))?,
220 ),
221 "Gbps" | "gbps" | "Gbit/s" | "gbit/s" | "Gb/s" | "gb/s" => {
222 (n, parse_fraction(fraction, fraction_cnt, 9))
223 }
224 "Tbps" | "tbps" | "Tbit/s" | "tbit/s" | "Tb/s" | "tb/s" => {
225 let bps = parse_fraction(fraction, fraction_cnt, 12);
226 (n.mul(1000)?.add(bps / 1_000_000_000)?, bps % 1_000_000_000)
227 }
228 _ => {
229 return Err(Error::UnknownUnit {
230 start,
231 end,
232 unit: self.src[start..end].to_string(),
233 value: n,
234 });
235 }
236 };
237 let (gbps, bps) = (gbps + (bps / 1_000_000_000), (bps % 1_000_000_000) as u32);
238 let new_bandwidth = Bandwidth::new(gbps, bps);
239 self.current = self
240 .current
241 .checked_add(new_bandwidth)
242 .ok_or(Error::NumberOverflow)?;
243 Ok(())
244 }
245
246 fn parse(mut self) -> Result<Bandwidth, Error> {
247 let mut n = self.parse_first_char()?.ok_or(Error::Empty)?;
248 let mut decimal = false;
249 let mut fraction: u64 = 0;
250 let mut fraction_cnt: u32 = 0;
251 'outer: loop {
252 let mut off = self.off();
253 while let Some(c) = self.iter.next() {
254 match c {
255 '0'..='9' => {
256 if decimal {
257 if fraction_cnt >= FRACTION_PART_LIMIT {
258 continue;
259 }
260 fraction = fraction
261 .checked_mul(10)
262 .and_then(|x| x.checked_add(c as u64 - '0' as u64))
263 .ok_or(Error::NumberOverflow)?;
264 fraction_cnt += 1;
265 } else {
266 n = n
267 .checked_mul(10)
268 .and_then(|x| x.checked_add(c as u64 - '0' as u64))
269 .ok_or(Error::NumberOverflow)?;
270 }
271 }
272 c if c.is_whitespace() => {}
273 '_' => {}
274 '.' => {
275 if decimal {
276 return Err(Error::InvalidCharacter(off));
277 }
278 decimal = true;
279 }
280 'a'..='z' | 'A'..='Z' | '/' => {
281 break;
282 }
283 _ => {
284 return Err(Error::InvalidCharacter(off));
285 }
286 }
287 off = self.off();
288 }
289 let start = off;
290 let mut off = self.off();
291 while let Some(c) = self.iter.next() {
292 match c {
293 '0'..='9' => {
294 self.parse_unit(n, fraction, fraction_cnt, start, off)?;
295 n = c as u64 - '0' as u64;
296 fraction = 0;
297 decimal = false;
298 fraction_cnt = 0;
299 continue 'outer;
300 }
301 c if c.is_whitespace() => break,
302 'a'..='z' | 'A'..='Z' | '/' => {}
303 _ => {
304 return Err(Error::InvalidCharacter(off));
305 }
306 }
307 off = self.off();
308 }
309 self.parse_unit(n, fraction, fraction_cnt, start, off)?;
310 n = match self.parse_first_char()? {
311 Some(n) => n,
312 None => return Ok(self.current),
313 };
314 fraction = 0;
315 decimal = false;
316 fraction_cnt = 0;
317 }
318 }
319}
320
321pub fn parse_bandwidth(s: &str) -> Result<Bandwidth, Error> {
348 Parser::new(s).parse()
349}
350
351pub fn format_bandwidth(val: Bandwidth) -> FormattedBandwidth {
385 FormattedBandwidth(val)
386}
387
388fn item(f: &mut fmt::Formatter, started: &mut bool, name: &str, value: u32) -> fmt::Result {
389 if value > 0 {
390 if *started {
391 f.write_str(" ")?;
392 }
393 write!(f, "{}{}", value, name)?;
394 *started = true;
395 }
396 Ok(())
397}
398
399#[derive(Copy, Clone)]
400#[repr(usize)]
401enum LargestUnit {
402 Bps = 0,
403 Kbps = 1,
404 Mbps = 2,
405 Gbps = 3,
406 Tbps = 4,
407}
408
409impl fmt::Display for LargestUnit {
410 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
411 match self {
412 LargestUnit::Bps => f.write_str("bps"),
413 LargestUnit::Kbps => f.write_str("kbps"),
414 LargestUnit::Mbps => f.write_str("Mbps"),
415 LargestUnit::Gbps => f.write_str("Gbps"),
416 LargestUnit::Tbps => f.write_str("Tbps"),
417 }
418 }
419}
420
421impl FormattedBandwidth {
422 #[deprecated(since = "0.1.4", note = "please use `core::ops::Deref` instead")]
423 pub fn get_ref(&self) -> &Bandwidth {
425 &self.0
426 }
427
428 pub fn fmt_integer(&self, f: &mut fmt::Formatter) -> fmt::Result {
432 let gbps = self.0.as_gbps();
433 let bps = self.0.subgbps_bps();
434
435 if gbps == 0 && bps == 0 {
436 f.write_str("0bps")?;
437 return Ok(());
438 }
439
440 let tbps = gbps / 1_000;
441 let gbps = gbps % 1_000;
442
443 let mbps = bps / 1_000_000;
444 let kbps = bps / 1_000 % 1_000;
445 let bps = bps % 1_000;
446
447 let started = &mut false;
448 item(f, started, "Tbps", tbps as u32)?;
449 item(f, started, "Gbps", gbps as u32)?;
450 item(f, started, "Mbps", mbps)?;
451 item(f, started, "kbps", kbps)?;
452 item(f, started, "bps", bps)?;
453 Ok(())
454 }
455
456 pub fn fmt_decimal(&self, f: &mut fmt::Formatter) -> fmt::Result {
460 let gbps = self.0.as_gbps();
461 let bps = self.0.subgbps_bps();
462
463 if gbps == 0 && bps == 0 {
464 f.write_str("0bps")?;
465 return Ok(());
466 }
467
468 let tbps = gbps / 1_000;
469 let gbps = gbps % 1_000;
470
471 let mbps = (bps / 1_000_000) as u64;
472 let kbps = (bps / 1_000 % 1_000) as u64;
473 let bps = (bps % 1_000) as u64;
474
475 let largest_unit = if tbps > 0 {
476 LargestUnit::Tbps
477 } else if gbps > 0 {
478 LargestUnit::Gbps
479 } else if mbps > 0 {
480 LargestUnit::Mbps
481 } else if kbps > 0 {
482 LargestUnit::Kbps
483 } else {
484 LargestUnit::Bps
485 };
486
487 let values = [bps, kbps, mbps, gbps, tbps];
488 let mut index = largest_unit as usize;
489 let mut zeros = 0;
490 let mut dot = true;
491 write!(f, "{}", values[index])?;
492 loop {
493 if index == 0 {
494 write!(f, "{}", largest_unit)?;
495 break;
496 }
497 index -= 1;
498 let value = values[index];
499 if value == 0 {
500 zeros += 3;
501 continue;
502 } else {
503 if dot {
504 f.write_str(".")?;
505 dot = false;
506 }
507 if zeros > 0 {
508 write!(f, "{:0width$}", 0, width = zeros)?;
509 zeros = 0;
510 }
511 if value % 10 != 0 {
512 write!(f, "{:03}", value)?;
513 } else if value % 100 != 0 {
514 write!(f, "{:02}", value / 10)?;
515 zeros += 1;
516 } else {
517 write!(f, "{}", value / 100)?;
518 zeros += 2;
519 }
520 }
521 }
522 Ok(())
523 }
524}
525
526impl fmt::Display for FormattedBandwidth {
527 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
528 #[cfg(not(feature = "display-integer"))]
529 self.fmt_decimal(f)?;
530 #[cfg(feature = "display-integer")]
531 self.fmt_integer(f)?;
532 Ok(())
533 }
534}
535
536impl core::ops::Deref for FormattedBandwidth {
537 type Target = Bandwidth;
538
539 fn deref(&self) -> &Bandwidth {
540 &self.0
541 }
542}
543
544impl core::ops::DerefMut for FormattedBandwidth {
545 fn deref_mut(&mut self) -> &mut Bandwidth {
546 &mut self.0
547 }
548}
549
550#[cfg(test)]
551mod tests {
552 use super::*;
553 use bandwidth::Bandwidth;
554
555 #[test]
556 fn test_units() {
557 assert_eq!(parse_bandwidth("1bps"), Ok(Bandwidth::new(0, 1)));
558 assert_eq!(parse_bandwidth("2bit/s"), Ok(Bandwidth::new(0, 2)));
559 assert_eq!(parse_bandwidth("15b/s"), Ok(Bandwidth::new(0, 15)));
560 assert_eq!(parse_bandwidth("51kbps"), Ok(Bandwidth::new(0, 51_000)));
561 assert_eq!(parse_bandwidth("79Kbps"), Ok(Bandwidth::new(0, 79_000)));
562 assert_eq!(parse_bandwidth("81kbit/s"), Ok(Bandwidth::new(0, 81_000)));
563 assert_eq!(parse_bandwidth("100Kbit/s"), Ok(Bandwidth::new(0, 100_000)));
564 assert_eq!(parse_bandwidth("150kb/s"), Ok(Bandwidth::new(0, 150_000)));
565 assert_eq!(parse_bandwidth("410Kb/s"), Ok(Bandwidth::new(0, 410_000)));
566 assert_eq!(parse_bandwidth("12Mbps"), Ok(Bandwidth::new(0, 12_000_000)));
567 assert_eq!(parse_bandwidth("16mbps"), Ok(Bandwidth::new(0, 16_000_000)));
568 assert_eq!(
569 parse_bandwidth("24Mbit/s"),
570 Ok(Bandwidth::new(0, 24_000_000))
571 );
572 assert_eq!(
573 parse_bandwidth("36mbit/s"),
574 Ok(Bandwidth::new(0, 36_000_000))
575 );
576 assert_eq!(parse_bandwidth("48Mb/s"), Ok(Bandwidth::new(0, 48_000_000)));
577 assert_eq!(parse_bandwidth("96mb/s"), Ok(Bandwidth::new(0, 96_000_000)));
578 assert_eq!(parse_bandwidth("2Gbps"), Ok(Bandwidth::new(2, 0)));
579 assert_eq!(parse_bandwidth("4gbps"), Ok(Bandwidth::new(4, 0)));
580 assert_eq!(parse_bandwidth("6Gbit/s"), Ok(Bandwidth::new(6, 0)));
581 assert_eq!(parse_bandwidth("8gbit/s"), Ok(Bandwidth::new(8, 0)));
582 assert_eq!(parse_bandwidth("16Gb/s"), Ok(Bandwidth::new(16, 0)));
583 assert_eq!(parse_bandwidth("40gb/s"), Ok(Bandwidth::new(40, 0)));
584 assert_eq!(parse_bandwidth("1Tbps"), Ok(Bandwidth::new(1_000, 0)));
585 assert_eq!(parse_bandwidth("2tbps"), Ok(Bandwidth::new(2_000, 0)));
586 assert_eq!(parse_bandwidth("4Tbit/s"), Ok(Bandwidth::new(4_000, 0)));
587 assert_eq!(parse_bandwidth("8tbit/s"), Ok(Bandwidth::new(8_000, 0)));
588 assert_eq!(parse_bandwidth("16Tb/s"), Ok(Bandwidth::new(16_000, 0)));
589 assert_eq!(parse_bandwidth("32tb/s"), Ok(Bandwidth::new(32_000, 0)));
590 }
591
592 #[test]
593 fn test_decimal() {
594 assert_eq!(parse_bandwidth("1.5bps"), Ok(Bandwidth::new(0, 1)));
595 assert_eq!(parse_bandwidth("2.5bit/s"), Ok(Bandwidth::new(0, 2)));
596 assert_eq!(parse_bandwidth("15.5b/s"), Ok(Bandwidth::new(0, 15)));
597 assert_eq!(parse_bandwidth("51.6kbps"), Ok(Bandwidth::new(0, 51_600)));
598 assert_eq!(parse_bandwidth("79.78Kbps"), Ok(Bandwidth::new(0, 79_780)));
599 assert_eq!(
600 parse_bandwidth("81.923kbit/s"),
601 Ok(Bandwidth::new(0, 81_923))
602 );
603 assert_eq!(
604 parse_bandwidth("100.1234Kbit/s"),
605 Ok(Bandwidth::new(0, 100_123))
606 );
607 assert_eq!(
608 parse_bandwidth("150.12345kb/s"),
609 Ok(Bandwidth::new(0, 150_123))
610 );
611 assert_eq!(
612 parse_bandwidth("410.123456Kb/s"),
613 Ok(Bandwidth::new(0, 410_123))
614 );
615 assert_eq!(
616 parse_bandwidth("12.123Mbps"),
617 Ok(Bandwidth::new(0, 12_123_000))
618 );
619 assert_eq!(
620 parse_bandwidth("16.1234mbps"),
621 Ok(Bandwidth::new(0, 16_123_400))
622 );
623 assert_eq!(
624 parse_bandwidth("24.12345Mbit/s"),
625 Ok(Bandwidth::new(0, 24_123_450))
626 );
627 assert_eq!(
628 parse_bandwidth("36.123456mbit/s"),
629 Ok(Bandwidth::new(0, 36_123_456))
630 );
631 assert_eq!(
632 parse_bandwidth("48.123Mb/s"),
633 Ok(Bandwidth::new(0, 48_123_000))
634 );
635 assert_eq!(
636 parse_bandwidth("96.1234mb/s"),
637 Ok(Bandwidth::new(0, 96_123_400))
638 );
639 assert_eq!(
640 parse_bandwidth("2.123Gbps"),
641 Ok(Bandwidth::new(2, 123_000_000))
642 );
643 assert_eq!(
644 parse_bandwidth("4.1234gbps"),
645 Ok(Bandwidth::new(4, 123_400_000))
646 );
647 assert_eq!(
648 parse_bandwidth("6.12345Gbit/s"),
649 Ok(Bandwidth::new(6, 123_450_000))
650 );
651 assert_eq!(
652 parse_bandwidth("8.123456gbit/s"),
653 Ok(Bandwidth::new(8, 123_456_000))
654 );
655 assert_eq!(
656 parse_bandwidth("16.123456789Gb/s"),
657 Ok(Bandwidth::new(16, 123_456_789))
658 );
659 assert_eq!(
660 parse_bandwidth("40.12345678912gb/s"),
661 Ok(Bandwidth::new(40, 123_456_789))
662 );
663 assert_eq!(parse_bandwidth("1.123Tbps"), Ok(Bandwidth::new(1_123, 0)));
664 assert_eq!(
665 parse_bandwidth("2.1234tbps"),
666 Ok(Bandwidth::new(2_123, 400_000_000))
667 );
668 assert_eq!(
669 parse_bandwidth("4.12345Tbit/s"),
670 Ok(Bandwidth::new(4_123, 450_000_000))
671 );
672 assert_eq!(
673 parse_bandwidth("8.123456tbit/s"),
674 Ok(Bandwidth::new(8_123, 456_000_000))
675 );
676 assert_eq!(
677 parse_bandwidth("16.123456789Tb/s"),
678 Ok(Bandwidth::new(16_123, 456_789_000))
679 );
680 assert_eq!(
681 parse_bandwidth("32.12345678912tb/s"),
682 Ok(Bandwidth::new(32_123, 456_789_120))
683 );
684 }
685
686 #[test]
687 fn test_combo() {
688 assert_eq!(
689 parse_bandwidth("1bps 2bit/s 3b/s"),
690 Ok(Bandwidth::new(0, 6))
691 );
692 assert_eq!(
693 parse_bandwidth("4kbps 5Kbps 6kbit/s"),
694 Ok(Bandwidth::new(0, 15_000))
695 );
696 assert_eq!(
697 parse_bandwidth("7Mbps 8mbps 9Mbit/s"),
698 Ok(Bandwidth::new(0, 24_000_000))
699 );
700 assert_eq!(
701 parse_bandwidth("10Gbps 11gbps 12Gbit/s"),
702 Ok(Bandwidth::new(33, 0))
703 );
704 assert_eq!(
705 parse_bandwidth("13Tbps 14tbps 15Tbit/s"),
706 Ok(Bandwidth::new(42_000, 0))
707 );
708 assert_eq!(
709 parse_bandwidth("10Gbps 5Mbps 1b/s"),
710 Ok(Bandwidth::new(10, 5_000_001))
711 );
712 assert_eq!(
713 parse_bandwidth("36Mbps 12kbps 24bps"),
714 Ok(Bandwidth::new(0, 36_012_024))
715 );
716 }
717
718 #[test]
719 fn test_decimal_combo() {
720 assert_eq!(
721 parse_bandwidth("1.1bps 2.2bit/s 3.3b/s"),
722 Ok(Bandwidth::new(0, 6))
723 );
724 assert_eq!(
725 parse_bandwidth("4.4kbps 5.5Kbps 6.6kbit/s"),
726 Ok(Bandwidth::new(0, 16_500))
727 );
728 assert_eq!(
729 parse_bandwidth("7.7Mbps 8.8mbps 9.9Mbit/s"),
730 Ok(Bandwidth::new(0, 26_400_000))
731 );
732 assert_eq!(
733 parse_bandwidth("10.10Gbps 11.11gbps 12.12Gbit/s"),
734 Ok(Bandwidth::new(33, 330_000_000))
735 );
736 assert_eq!(
737 parse_bandwidth("13.13Tbps 14.14tbps 15.15Tbit/s"),
738 Ok(Bandwidth::new(42_420, 0))
739 );
740 assert_eq!(
741 parse_bandwidth("10.1Gbps 5.2Mbps 1.3b/s"),
742 Ok(Bandwidth::new(10, 105_200_001))
743 );
744 assert_eq!(
745 parse_bandwidth("36.1Mbps 12.2kbps 24.3bps"),
746 Ok(Bandwidth::new(0, 36_112_224))
747 );
748 }
749
750 #[test]
751 fn test_overflow() {
752 assert_eq!(
753 parse_bandwidth("100000000000000000000bps"),
754 Err(Error::NumberOverflow)
755 );
756 assert_eq!(
757 parse_bandwidth("100000000000000000kbps"),
758 Err(Error::NumberOverflow)
759 );
760 assert_eq!(
761 parse_bandwidth("100000000000000Mbps"),
762 Err(Error::NumberOverflow)
763 );
764 assert_eq!(
765 parse_bandwidth("100000000000000000000Gbps"),
766 Err(Error::NumberOverflow)
767 );
768 assert_eq!(
769 parse_bandwidth("10000000000000000000Tbps"),
770 Err(Error::NumberOverflow)
771 );
772 }
773
774 #[test]
775 fn test_nice_error_message() {
776 assert_eq!(
777 parse_bandwidth("123").unwrap_err().to_string(),
778 "bandwidth unit needed, for example 123Mbps or 123bps"
779 );
780 assert_eq!(
781 parse_bandwidth("10 Gbps 1").unwrap_err().to_string(),
782 "bandwidth unit needed, for example 1Mbps or 1bps"
783 );
784 assert_eq!(
785 parse_bandwidth("10 byte/s").unwrap_err().to_string(),
786 "unknown bandwidth unit \"byte/s\", \
787 supported units: bps, kbps, Mbps, Gbps, Tbps"
788 );
789 }
790
791 #[test]
792 fn test_formatted_bandwidth_integer() {
793 struct TestInteger(FormattedBandwidth);
794 impl From<FormattedBandwidth> for TestInteger {
795 fn from(fb: FormattedBandwidth) -> Self {
796 TestInteger(fb)
797 }
798 }
799 impl fmt::Display for TestInteger {
800 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
801 self.0.fmt_integer(f)
802 }
803 }
804 assert_eq!(
805 TestInteger::from(format_bandwidth(Bandwidth::new(0, 0))).to_string(),
806 "0bps"
807 );
808 assert_eq!(
809 TestInteger::from(format_bandwidth(Bandwidth::new(0, 1))).to_string(),
810 "1bps"
811 );
812 assert_eq!(
813 TestInteger::from(format_bandwidth(Bandwidth::new(0, 15))).to_string(),
814 "15bps"
815 );
816 assert_eq!(
817 TestInteger::from(format_bandwidth(Bandwidth::new(0, 51_000))).to_string(),
818 "51kbps"
819 );
820 assert_eq!(
821 TestInteger::from(format_bandwidth(Bandwidth::new(0, 32_000_000))).to_string(),
822 "32Mbps"
823 );
824 assert_eq!(
825 TestInteger::from(format_bandwidth(Bandwidth::new(0, 79_000_000))).to_string(),
826 "79Mbps"
827 );
828 assert_eq!(
829 TestInteger::from(format_bandwidth(Bandwidth::new(0, 100_000_000))).to_string(),
830 "100Mbps"
831 );
832 assert_eq!(
833 TestInteger::from(format_bandwidth(Bandwidth::new(0, 150_000_000))).to_string(),
834 "150Mbps"
835 );
836 assert_eq!(
837 TestInteger::from(format_bandwidth(Bandwidth::new(0, 410_000_000))).to_string(),
838 "410Mbps"
839 );
840 assert_eq!(
841 TestInteger::from(format_bandwidth(Bandwidth::new(1, 0))).to_string(),
842 "1Gbps"
843 );
844 assert_eq!(
845 TestInteger::from(format_bandwidth(Bandwidth::new(4, 500_000_000))).to_string(),
846 "4Gbps 500Mbps"
847 );
848 assert_eq!(
849 TestInteger::from(format_bandwidth(Bandwidth::new(9420, 0))).to_string(),
850 "9Tbps 420Gbps"
851 );
852 }
853
854 #[test]
855 fn test_formatted_bandwidth_decimal() {
856 struct TestDecimal(FormattedBandwidth);
857 impl From<FormattedBandwidth> for TestDecimal {
858 fn from(fb: FormattedBandwidth) -> Self {
859 TestDecimal(fb)
860 }
861 }
862 impl fmt::Display for TestDecimal {
863 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
864 self.0.fmt_decimal(f)
865 }
866 }
867 assert_eq!(
868 TestDecimal::from(format_bandwidth(Bandwidth::new(0, 0))).to_string(),
869 "0bps"
870 );
871 assert_eq!(
872 TestDecimal::from(format_bandwidth(Bandwidth::new(0, 1))).to_string(),
873 "1bps"
874 );
875 assert_eq!(
876 TestDecimal::from(format_bandwidth(Bandwidth::new(0, 15))).to_string(),
877 "15bps"
878 );
879 assert_eq!(
880 TestDecimal::from(format_bandwidth(Bandwidth::new(0, 51_200))).to_string(),
881 "51.2kbps"
882 );
883 assert_eq!(
884 TestDecimal::from(format_bandwidth(Bandwidth::new(0, 32_300_400))).to_string(),
885 "32.3004Mbps"
886 );
887 assert_eq!(
888 TestDecimal::from(format_bandwidth(Bandwidth::new(0, 79_000_050))).to_string(),
889 "79.00005Mbps"
890 );
891 assert_eq!(
892 TestDecimal::from(format_bandwidth(Bandwidth::new(0, 100_060_007))).to_string(),
893 "100.060007Mbps"
894 );
895 assert_eq!(
896 TestDecimal::from(format_bandwidth(Bandwidth::new(0, 150_000_000))).to_string(),
897 "150Mbps"
898 );
899 assert_eq!(
900 TestDecimal::from(format_bandwidth(Bandwidth::new(0, 410_008_900))).to_string(),
901 "410.0089Mbps"
902 );
903 assert_eq!(
904 TestDecimal::from(format_bandwidth(Bandwidth::new(1, 0))).to_string(),
905 "1Gbps"
906 );
907 assert_eq!(
908 TestDecimal::from(format_bandwidth(Bandwidth::new(4, 500_000_000))).to_string(),
909 "4.5Gbps"
910 );
911 assert_eq!(
912 TestDecimal::from(format_bandwidth(Bandwidth::new(8700, 32_000_000))).to_string(),
913 "8.700032Tbps"
914 );
915 assert_eq!(
916 "9.42Tbps",
917 TestDecimal::from(format_bandwidth(Bandwidth::new(9420, 0))).to_string(),
918 );
919 }
920}