use crate::error::{CliError, Result}; use serde_json::Value; use std::{ fs, io, path::{Path, PathBuf}, }; pub fn read_file_to_json(path: &PathBuf) -> Result { let content = fs::read_to_string(path).map_err(|e| io_error("读取文件", path, e))?; serde_json::from_str(&content).map_err(|e| { CliError::InvalidData(format!("解析 JSON '{}' 失败: {}", path.display(), e)) }) } pub fn write_json_to_file(path: &PathBuf, value: &Value) -> Result<()> { let content = serde_json::to_string_pretty(value).map_err(|e| { CliError::InvalidData(format!("序列化 JSON '{}' 失败: {}", path.display(), e)) })?; fs::write(path, content).map_err(|e| io_error("写入文件", path, e))?; Ok(()) } pub fn update_json_file(path: &PathBuf, updater: F) -> Result<()> where F: FnOnce(&mut Value) -> Result<()>, { let mut json = read_file_to_json(path)?; updater(&mut json)?; write_json_to_file(path, &json)?; Ok(()) } pub fn find_project_dir(path: &Option) -> Result { let path = path.as_deref().unwrap_or("."); Ok(PathBuf::from(path)) } /// Wraps an [`io::Error`] with the operation name and path so error messages /// stop being anonymous "os error 3" strings. pub fn io_error(op: &str, path: &Path, err: io::Error) -> CliError { CliError::Io(io::Error::new( err.kind(), format!("{} '{}' 失败: {}", op, path.display(), err), )) }