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