net_bytes/
lib.rs

1mod download_acceleration;
2mod download_speed;
3mod file_size;
4
5use std::fmt::{self, Display};
6
7pub use download_acceleration::DownloadAcceleration;
8pub use download_speed::DownloadSpeed;
9pub use file_size::{FileSize, NonZeroFileSize};
10
11/// Scale factor for fixed-point arithmetic (6 decimal places)
12/// 
13/// 定点数的缩放因子(6位小数精度)
14pub(crate) const SCALE: u128 = 1_000_000;
15pub(crate) const SCALE_I128: i128 = 1_000_000;
16
17/// A trait for types that can be formatted as file sizes
18///
19/// 可以格式化为文件大小的 trait
20pub trait FileSizeFormat: Sized {
21    /// Returns the formatted value and unit in SI (base-1000) standard
22    ///
23    /// 返回 SI (base-1000) 标准的 (formatted_value, unit)
24    fn get_si_parts(&self) -> (String, &'static str);
25
26    /// Returns the formatted value and unit in IEC (base-1024) standard
27    ///
28    /// 返回 IEC (base-1024) 标准的 (formatted_value, unit)
29    fn get_iec_parts(&self) -> (String, &'static str);
30
31    /// Returns a formatted string in SI (base-1000) standard
32    ///
33    /// 返回 SI (base-1000) 标准的格式化字符串
34    #[inline]
35    fn to_si_string(&self) -> String {
36        let (value, unit) = self.get_si_parts();
37        format!("{} {}", value, unit)
38    }
39
40    /// Returns a formatted string in IEC (base-1024) standard
41    ///
42    /// 返回 IEC (base-1024) 标准的格式化字符串
43    #[inline]
44    fn to_iec_string(&self) -> String {
45        let (value, unit) = self.get_iec_parts();
46        format!("{} {}", value, unit)
47    }
48
49    #[inline]
50    fn to_formatted(self, standard: SizeStandard) -> FormattedValue<Self> {
51        FormattedValue::new(self, standard)
52    }
53}
54
55pub struct FormattedValue<T: FileSizeFormat> {
56    value: T,
57    standard: SizeStandard,
58}
59
60impl<T: FileSizeFormat> FormattedValue<T> {
61    pub fn new(value: T, standard: SizeStandard) -> Self {
62        Self { value, standard }
63    }
64
65    pub fn get_value(&self) -> &T {
66        &self.value
67    }
68}
69
70impl<T: FileSizeFormat> Display for FormattedValue<T> {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        let display = match self.standard {
73            SizeStandard::SI => self.value.to_si_string(),
74            SizeStandard::IEC => self.value.to_iec_string(),
75        };
76        write!(f, "{}", display)
77    }
78}
79
80/// Standard for file size units
81///
82/// 文件大小单位标准
83#[derive(Debug, Clone, Copy)]
84pub enum SizeStandard {
85    /// SI standard (base-1000, units: KB, MB)
86    ///
87    /// SI 标准 (base-1000, 单位 KB, MB)
88    SI,
89    /// IEC standard (base-1024, units: KiB, MiB)
90    ///
91    /// IEC 标准 (base-1024, 单位 KiB, MiB)
92    IEC,
93}
94
95/// Format a scaled fixed-point value and return (formatted_value, unit)
96/// 
97/// The input `scaled_value` should be the actual value multiplied by SCALE.
98///
99/// 格式化定点数值,返回 (formatted_value, unit)
100/// 
101/// 输入的 `scaled_value` 应该是实际值乘以 SCALE。
102pub(crate) fn format_parts_scaled(
103    mut scaled_value: u128,
104    base: u128,
105    units: &'static [&'static str],
106) -> (String, &'static str) {
107    let mut unit_index = 0;
108    let base_scaled = base * SCALE;
109
110    while scaled_value >= base_scaled && unit_index < units.len() - 1 {
111        // scaled_value = scaled_value / base (keeping the scale)
112        scaled_value = scaled_value * SCALE / base_scaled;
113        unit_index += 1;
114    }
115
116    let formatted_value = format_scaled_value(scaled_value);
117    (formatted_value, units[unit_index])
118}
119
120/// Format a scaled fixed-point value for signed types (acceleration)
121///
122/// 格式化有符号定点数值(用于加速度)
123pub(crate) fn format_parts_scaled_signed(
124    scaled_value: i128,
125    base: u128,
126    units: &'static [&'static str],
127) -> (String, &'static str) {
128    let is_negative = scaled_value < 0;
129    let abs_value = scaled_value.unsigned_abs();
130    
131    let (formatted, unit) = format_parts_scaled(abs_value, base, units);
132    
133    if is_negative {
134        (format!("-{}", formatted), unit)
135    } else {
136        (formatted, unit)
137    }
138}
139
140/// Format a scaled value with automatic decimal places selection
141/// - Less than 10: 2 decimal places
142/// - 10 or greater: 1 decimal place
143///
144/// 格式化缩放后的值,根据值的大小自动选择小数位数
145/// - 小于10: 显示2位小数
146/// - 大于等于10: 显示1位小数
147#[inline]
148pub(crate) fn format_scaled_value(scaled_value: u128) -> String {
149    // Convert from SCALE (1_000_000) to the display format
150    let integer_part = scaled_value / SCALE;
151    let fractional_part = scaled_value % SCALE;
152    
153    if integer_part < 10 {
154        // 2 decimal places: round to nearest 0.01
155        // fractional_part is in millionths, we need hundredths
156        let hundredths = (fractional_part + 5000) / 10000; // round to 2 decimal places
157        let hundredths = if hundredths >= 100 {
158            // Carry over to integer part handled by checking
159            return format!("{:.2}", (integer_part + 1) as f64);
160        } else {
161            hundredths
162        };
163        format!("{}.{:02}", integer_part, hundredths)
164    } else {
165        // 1 decimal place: round to nearest 0.1
166        let tenths = (fractional_part + 50000) / 100000; // round to 1 decimal place
167        if tenths >= 10 {
168            format!("{}.0", integer_part + 1)
169        } else {
170            format!("{}.{}", integer_part, tenths)
171        }
172    }
173}