1 pub mod fstype; 2 pub mod partition; 3 4 mod utils; 5 6 use std::{fs, path::PathBuf}; 7 8 use anyhow::Result; 9 use fstype::FsType; 10 use partition::PartitionConfig; 11 use serde::Deserialize; 12 13 /// rootfs配置文件 14 #[derive(Debug, Clone, Deserialize)] 15 pub struct RootFSConfigFile { 16 pub metadata: RootFSMeta, 17 #[serde(default)] 18 pub partition: PartitionConfig, 19 } 20 21 impl RootFSConfigFile { 22 pub const LBA_SIZE: usize = 512; 23 pub fn load(path: &PathBuf) -> Result<Self> { 24 // 读取文件内容 25 let content = fs::read_to_string(path)?; 26 Self::load_from_str(&content) 27 } 28 29 pub fn load_from_str(content: &str) -> Result<Self> { 30 let config: RootFSConfigFile = toml::from_str(content)?; 31 32 Ok(config) 33 } 34 } 35 36 #[derive(Debug, Clone, Copy, Deserialize)] 37 pub struct RootFSMeta { 38 /// rootfs文件系统类型 39 pub fs_type: FsType, 40 /// rootfs磁盘大小(至少要大于这个值) 41 /// 单位:字节 42 #[serde(deserialize_with = "utils::size::deserialize_size")] 43 pub size: usize, 44 } 45 46 #[cfg(test)] 47 mod tests { 48 use std::io::Write; 49 50 use super::*; 51 use tempfile::NamedTempFile; 52 53 #[test] 54 fn test_load_from_valid_file() { 55 let config_content = r#" 56 [metadata] 57 fs_type = "fat32" 58 size = "1024M" 59 "#; 60 61 let mut temp_file = NamedTempFile::new().expect("Failed to create temp file"); 62 temp_file 63 .write_all(config_content.as_bytes()) 64 .expect("Failed to write to temp file"); 65 66 let config_path = PathBuf::from(temp_file.path()); 67 let config = RootFSConfigFile::load(&config_path).expect("Failed to load config"); 68 69 assert_eq!(config.metadata.fs_type, FsType::Fat32); 70 assert_eq!(config.metadata.size, 1024 * 1024 * 1024); // Assuming `deserialize_size` converts MB to Bytes 71 } 72 73 #[test] 74 fn test_load_from_valid_str() { 75 let config_content = r#" 76 [metadata] 77 fs_type = "fat32" 78 size = "512M" 79 "#; 80 81 let config = RootFSConfigFile::load_from_str(config_content) 82 .expect("Failed to load config from str"); 83 84 assert_eq!(config.metadata.fs_type, FsType::Fat32); 85 assert_eq!(config.metadata.size, 512 * 1024 * 1024); // Assuming `deserialize_size` converts MB to Bytes 86 } 87 #[test] 88 fn test_load_from_invalid_fs_type() { 89 let config_content = r#" 90 [metadata] 91 fs_type = "ABCDE" 92 size = "512M" 93 "#; 94 assert!(RootFSConfigFile::load_from_str(config_content).is_err()); 95 } 96 97 /// 测试size为int类型的字节大小 98 #[test] 99 fn test_load_from_valid_str_size_integer() { 100 let config_content = r#" 101 [metadata] 102 fs_type = "fat32" 103 size = 1048576 104 "#; 105 106 let config = RootFSConfigFile::load_from_str(config_content) 107 .expect("Failed to load config from str"); 108 109 assert_eq!(config.metadata.fs_type, FsType::Fat32); 110 assert_eq!(config.metadata.size, 1048576); // Assuming `deserialize_size` converts MB to Bytes 111 } 112 #[test] 113 fn test_load_from_valid_str_size_bytes_str() { 114 let config_content = r#" 115 [metadata] 116 fs_type = "fat32" 117 size = "1048576" 118 "#; 119 120 let config = RootFSConfigFile::load_from_str(config_content) 121 .expect("Failed to load config from str"); 122 123 assert_eq!(config.metadata.fs_type, FsType::Fat32); 124 assert_eq!(config.metadata.size, 1048576); // Assuming `deserialize_size` converts MB to Bytes 125 } 126 127 #[test] 128 fn test_load_from_invalid_file() { 129 let temp_file = NamedTempFile::new().expect("Failed to create temp file"); 130 let config_path = PathBuf::from(temp_file.path()); 131 132 assert!(RootFSConfigFile::load(&config_path).is_err()); 133 } 134 135 /// Parse from an incorrect size field (string) 136 #[test] 137 fn test_load_from_invalid_size_str() { 138 let invalid_config_content = r#" 139 [metadata] 140 fs_type = "fat32" 141 size = "not_a_size" 142 "#; 143 144 assert!(RootFSConfigFile::load_from_str(invalid_config_content).is_err()); 145 } 146 147 /// Parse from an incorrect size field (array) 148 #[test] 149 fn test_load_from_invalid_size_array() { 150 // The 'size' field should not be an array 151 let invalid_config_content = r#" 152 [metadata] 153 fs_type = "fat32" 154 size = ["not_a_size"] 155 "#; 156 157 assert!(RootFSConfigFile::load_from_str(invalid_config_content).is_err()); 158 } 159 } 160