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