net_bytes/
lib.rs

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
15/// A trait for types that can be formatted as file sizes
16///
17/// 可以格式化为文件大小的 trait
18pub trait FileSizeFormat: Sized {
19    /// Returns the formatted value and unit in SI (base-1000) standard
20    ///
21    /// 返回 SI (base-1000) 标准的 (formatted_value, unit)
22    fn get_si_parts(&self) -> (String, &'static str);
23
24    /// Returns the formatted value and unit in IEC (base-1024) standard
25    ///
26    /// 返回 IEC (base-1024) 标准的 (formatted_value, unit)
27    fn get_iec_parts(&self) -> (String, &'static str);
28
29    /// Returns a formatted string in SI (base-1000) standard
30    ///
31    /// 返回 SI (base-1000) 标准的格式化字符串
32    #[inline]
33    fn to_si_string(&self) -> String {
34        let (value, unit) = self.get_si_parts();
35        format!("{} {}", value, unit)
36    }
37
38    /// Returns a formatted string in IEC (base-1024) standard
39    ///
40    /// 返回 IEC (base-1024) 标准的格式化字符串
41    #[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/// Standard for file size units
79///
80/// 文件大小单位标准
81#[derive(Debug, Clone, Copy)]
82pub enum SizeStandard {
83    /// SI standard (base-1000, units: KB, MB)
84    ///
85    /// SI 标准 (base-1000, 单位 KB, MB)
86    SI,
87    /// IEC standard (base-1024, units: KiB, MiB)
88    ///
89    /// IEC 标准 (base-1024, 单位 KiB, MiB)
90    IEC,
91}
92
93/// Format a numeric value and return (formatted_value, unit_index)
94///
95/// 格式化数值部分,返回 (formatted_value, unit_index)
96pub(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/// Format a decimal value with automatic decimal places selection based on value
113/// - Less than 10: 2 decimal places
114/// - 10 or greater: 1 decimal place
115///
116/// 格式化十进制数值,根据值的大小自动选择小数位数
117/// - 小于10: 显示2位小数
118/// - 大于等于10: 显示1位小数
119#[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}