xref: /DADK/dadk-config/src/rootfs/utils/size.rs (revision 1ad837a44976ed9fbcb8d70a0b0b47ea3286c5ed)
1*1ad837a4SLoGin use serde::Deserializer;
2*1ad837a4SLoGin 
3*1ad837a4SLoGin /// 自定义反序列化函数,用于解析表示磁盘镜像大小的值。
4*1ad837a4SLoGin ///
5*1ad837a4SLoGin /// 此函数支持两种输入格式:
6*1ad837a4SLoGin /// 1. 纯数字:直接将其视为字节数。
7*1ad837a4SLoGin /// 2. 带单位的字符串:如"1M"、"1G",其中单位支持K(千字节)、M(兆字节)、G(千兆字节)。
8*1ad837a4SLoGin ///
9*1ad837a4SLoGin /// 函数将输入值解析为`usize`类型,表示字节数。
10*1ad837a4SLoGin ///
11*1ad837a4SLoGin /// # 参数
12*1ad837a4SLoGin /// - `deserializer`: 一个实现了`Deserializer` trait的对象,用于读取和解析输入数据。
13*1ad837a4SLoGin ///
14*1ad837a4SLoGin /// # 返回值
15*1ad837a4SLoGin /// 返回一个`Result<usize, D::Error>`,其中:
16*1ad837a4SLoGin /// - `Ok(usize)`表示解析成功,返回对应的字节数。
17*1ad837a4SLoGin /// - `Err(D::Error)`表示解析失败,返回错误信息。
18*1ad837a4SLoGin ///
19*1ad837a4SLoGin /// # 错误处理
20*1ad837a4SLoGin /// - 如果输入是非法的字符串(无法解析或单位不合法),将返回自定义错误。
21*1ad837a4SLoGin /// - 如果输入类型既不是整数也不是字符串,将返回类型错误。
22*1ad837a4SLoGin pub fn deserialize_size<'de, D>(deserializer: D) -> Result<usize, D::Error>
23*1ad837a4SLoGin where
24*1ad837a4SLoGin     D: Deserializer<'de>,
25*1ad837a4SLoGin {
26*1ad837a4SLoGin     // 使用serde的deserialize_any方法来处理不同类型的输入
27*1ad837a4SLoGin     let value = serde::de::Deserialize::deserialize(deserializer)?;
28*1ad837a4SLoGin 
29*1ad837a4SLoGin     // 匹配输入值的类型,进行相应的转换
30*1ad837a4SLoGin     match value {
31*1ad837a4SLoGin         toml::Value::Integer(num) => {
32*1ad837a4SLoGin             // 如果是整数类型,直接转换成usize
33*1ad837a4SLoGin             Ok(num as usize)
34*1ad837a4SLoGin         }
35*1ad837a4SLoGin         toml::Value::String(s) => {
36*1ad837a4SLoGin             // 如果是字符串类型,解析如"1M"这样的表示
37*1ad837a4SLoGin             parse_size_from_string(&s)
38*1ad837a4SLoGin                 .ok_or_else(|| serde::de::Error::custom("Invalid string for size"))
39*1ad837a4SLoGin         }
40*1ad837a4SLoGin         _ => Err(serde::de::Error::custom("Invalid type for size")),
41*1ad837a4SLoGin     }
42*1ad837a4SLoGin }
43*1ad837a4SLoGin 
44*1ad837a4SLoGin /// Parses a size string with optional unit suffix (K, M, G) into a usize value.
45*1ad837a4SLoGin ///
46*1ad837a4SLoGin /// This function takes a string that represents a size, which can be a plain
47*1ad837a4SLoGin /// number or a number followed by a unit suffix (K for kilobytes, M for megabytes,
48*1ad837a4SLoGin /// G for gigabytes). It converts this string into an equivalent usize value in bytes.
49*1ad837a4SLoGin ///
50*1ad837a4SLoGin /// # Parameters
51*1ad837a4SLoGin /// - `size_str`: A string slice that contains the size to parse. This can be a simple
52*1ad837a4SLoGin ///   numeric string or a numeric string followed by a unit ('K', 'M', 'G').
53*1ad837a4SLoGin ///
54*1ad837a4SLoGin /// # Returns
55*1ad837a4SLoGin /// An `Option<usize>` where:
56*1ad837a4SLoGin /// - `Some(usize)` contains the parsed size in bytes if the input string is valid.
57*1ad837a4SLoGin /// - `None` if the input string is invalid or contains an unsupported unit.
58*1ad837a4SLoGin fn parse_size_from_string(size_str: &str) -> Option<usize> {
59*1ad837a4SLoGin     if size_str.chars().all(|c| c.is_ascii_digit()) {
60*1ad837a4SLoGin         // 如果整个字符串都是数字,直接解析返回
61*1ad837a4SLoGin         return size_str.parse::<usize>().ok();
62*1ad837a4SLoGin     }
63*1ad837a4SLoGin 
64*1ad837a4SLoGin     let mut chars = size_str.chars().rev();
65*1ad837a4SLoGin     let unit = chars.next()?;
66*1ad837a4SLoGin     let number_str: String = chars.rev().collect();
67*1ad837a4SLoGin     let number = number_str.parse::<usize>().ok()?;
68*1ad837a4SLoGin 
69*1ad837a4SLoGin     match unit.to_ascii_uppercase() {
70*1ad837a4SLoGin         'K' => Some(number * 1024),
71*1ad837a4SLoGin         'M' => Some(number * 1024 * 1024),
72*1ad837a4SLoGin         'G' => Some(number * 1024 * 1024 * 1024),
73*1ad837a4SLoGin         _ => None,
74*1ad837a4SLoGin     }
75*1ad837a4SLoGin }
76*1ad837a4SLoGin 
77*1ad837a4SLoGin #[cfg(test)]
78*1ad837a4SLoGin mod tests {
79*1ad837a4SLoGin     use super::*;
80*1ad837a4SLoGin 
81*1ad837a4SLoGin     #[test]
82*1ad837a4SLoGin     fn test_parse_size_from_string() {
83*1ad837a4SLoGin         // 正常情况,不带单位
84*1ad837a4SLoGin         assert_eq!(parse_size_from_string("1024"), Some(1024));
85*1ad837a4SLoGin 
86*1ad837a4SLoGin         // 正常情况,带有单位
87*1ad837a4SLoGin         assert_eq!(parse_size_from_string("1K"), Some(1024));
88*1ad837a4SLoGin         assert_eq!(parse_size_from_string("2M"), Some(2 * 1024 * 1024));
89*1ad837a4SLoGin         assert_eq!(parse_size_from_string("3G"), Some(3 * 1024 * 1024 * 1024));
90*1ad837a4SLoGin 
91*1ad837a4SLoGin         // 边界情况
92*1ad837a4SLoGin         assert_eq!(parse_size_from_string("0K"), Some(0));
93*1ad837a4SLoGin         assert_eq!(parse_size_from_string("0M"), Some(0));
94*1ad837a4SLoGin         assert_eq!(parse_size_from_string("0G"), Some(0));
95*1ad837a4SLoGin 
96*1ad837a4SLoGin         // 小写情况
97*1ad837a4SLoGin         assert_eq!(parse_size_from_string("1k"), Some(1024));
98*1ad837a4SLoGin         assert_eq!(parse_size_from_string("2m"), Some(2 * 1024 * 1024));
99*1ad837a4SLoGin         assert_eq!(parse_size_from_string("3g"), Some(3 * 1024 * 1024 * 1024));
100*1ad837a4SLoGin 
101*1ad837a4SLoGin         // 错误的单位
102*1ad837a4SLoGin         assert_eq!(parse_size_from_string("1T"), None);
103*1ad837a4SLoGin         assert_eq!(parse_size_from_string("2X"), None);
104*1ad837a4SLoGin 
105*1ad837a4SLoGin         // 错误的数字格式
106*1ad837a4SLoGin         assert_eq!(parse_size_from_string("aK"), None);
107*1ad837a4SLoGin         assert_eq!(parse_size_from_string("1.5M"), None);
108*1ad837a4SLoGin 
109*1ad837a4SLoGin         // 空字符串
110*1ad837a4SLoGin         assert_eq!(parse_size_from_string(""), None);
111*1ad837a4SLoGin 
112*1ad837a4SLoGin         // 只单位没有数字
113*1ad837a4SLoGin         assert_eq!(parse_size_from_string("K"), None);
114*1ad837a4SLoGin 
115*1ad837a4SLoGin         // 数字后有多余字符
116*1ad837a4SLoGin         assert_eq!(parse_size_from_string("1KextrK"), None);
117*1ad837a4SLoGin     }
118*1ad837a4SLoGin }
119