use serde::Deserializer;
use crate::rootfs::RootFSConfigFile;
pub fn deserialize_size<'de, D>(deserializer: D) -> Result<usize, D::Error>
where
D: Deserializer<'de>,
{
let value = serde::de::Deserialize::deserialize(deserializer)?;
let r = match value {
toml::Value::Integer(num) => {
Ok(num as usize)
}
toml::Value::String(s) => {
parse_size_from_string(&s)
.ok_or_else(|| serde::de::Error::custom("Invalid string for size"))
}
_ => Err(serde::de::Error::custom("Invalid type for size")),
};
r.map(|size| (size + RootFSConfigFile::LBA_SIZE - 1) & !(RootFSConfigFile::LBA_SIZE - 1))
}
fn parse_size_from_string(size_str: &str) -> Option<usize> {
if size_str.chars().all(|c| c.is_ascii_digit()) {
return size_str.parse::<usize>().ok();
}
let mut chars = size_str.chars().rev();
let unit = chars.next()?;
let number_str: String = chars.rev().collect();
let number = number_str.parse::<usize>().ok()?;
match unit.to_ascii_uppercase() {
'K' => Some(number * 1024),
'M' => Some(number * 1024 * 1024),
'G' => Some(number * 1024 * 1024 * 1024),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_size_from_string() {
assert_eq!(parse_size_from_string("1024"), Some(1024));
assert_eq!(parse_size_from_string("1K"), Some(1024));
assert_eq!(parse_size_from_string("2M"), Some(2 * 1024 * 1024));
assert_eq!(parse_size_from_string("3G"), Some(3 * 1024 * 1024 * 1024));
assert_eq!(parse_size_from_string("0K"), Some(0));
assert_eq!(parse_size_from_string("0M"), Some(0));
assert_eq!(parse_size_from_string("0G"), Some(0));
assert_eq!(parse_size_from_string("1k"), Some(1024));
assert_eq!(parse_size_from_string("2m"), Some(2 * 1024 * 1024));
assert_eq!(parse_size_from_string("3g"), Some(3 * 1024 * 1024 * 1024));
assert_eq!(parse_size_from_string("1T"), None);
assert_eq!(parse_size_from_string("2X"), None);
assert_eq!(parse_size_from_string("aK"), None);
assert_eq!(parse_size_from_string("1.5M"), None);
assert_eq!(parse_size_from_string(""), None);
assert_eq!(parse_size_from_string("K"), None);
assert_eq!(parse_size_from_string("1KextrK"), None);
}
}