1mod download_acceleration;
2mod download_speed;
3mod file_size;
4
5use std::fmt::{self, Display};
6
7use rust_decimal::Decimal;
8
9pub use download_acceleration::DownloadAcceleration;
10pub use download_speed::DownloadSpeed;
11pub use file_size::{FileSize, NonZeroFileSize};
12
13pub use rust_decimal;
14
15pub trait FileSizeFormat: Sized {
19 fn get_si_parts(&self) -> (String, &'static str);
23
24 fn get_iec_parts(&self) -> (String, &'static str);
28
29 #[inline]
33 fn to_si_string(&self) -> String {
34 let (value, unit) = self.get_si_parts();
35 format!("{} {}", value, unit)
36 }
37
38 #[inline]
42 fn to_iec_string(&self) -> String {
43 let (value, unit) = self.get_iec_parts();
44 format!("{} {}", value, unit)
45 }
46
47 #[inline]
48 fn to_formatted(self, standard: SizeStandard) -> FormattedValue<Self> {
49 FormattedValue::new(self, standard)
50 }
51}
52
53pub struct FormattedValue<T: FileSizeFormat> {
54 value: T,
55 standard: SizeStandard,
56}
57
58impl<T: FileSizeFormat> FormattedValue<T> {
59 pub fn new(value: T, standard: SizeStandard) -> Self {
60 Self { value, standard }
61 }
62
63 pub fn get_value(&self) -> &T {
64 &self.value
65 }
66}
67
68impl<T: FileSizeFormat> Display for FormattedValue<T> {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 let display = match self.standard {
71 SizeStandard::SI => self.value.to_si_string(),
72 SizeStandard::IEC => self.value.to_iec_string(),
73 };
74 write!(f, "{}", display)
75 }
76}
77
78#[derive(Debug, Clone, Copy)]
82pub enum SizeStandard {
83 SI,
87 IEC,
91}
92
93pub(crate) fn format_parts(
97 mut value: Decimal,
98 base: Decimal,
99 units: &'static [&'static str],
100) -> (String, &'static str) {
101 let mut unit_index = 0;
102
103 while value >= base && unit_index < units.len() - 1 {
104 value /= base;
105 unit_index += 1;
106 }
107
108 let formatted_value = format_decimal_value(value);
109 (formatted_value, units[unit_index])
110}
111
112#[inline]
120pub(crate) fn format_decimal_value(value: Decimal) -> String {
121 if value < Decimal::from(10) {
122 let mut rounded = value.round_dp(2);
123 rounded.rescale(2);
124 rounded.to_string()
125 } else {
126 let mut rounded = value.round_dp(1);
127 rounded.rescale(1);
128 rounded.to_string()
129 }
130}