转换错误类型
use std::error::Error; use std::fmt::{self, Display, Formatter}; use std::fs::{self, File}; use std::io::{self, Read}; #[derive(Debug)] enum ReadUsernameError { IoError(io::Error), EmptyUsername(String), } impl Error for ReadUsernameError {} impl Display for ReadUsernameError { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { Self::IoError(e) => write!(f, "IO error: {e}"), Self::EmptyUsername(filename) => write!(f, "Found no username in {filename}"), } } } impl From<io::Error> for ReadUsernameError { fn from(err: io::Error) -> ReadUsernameError { ReadUsernameError::IoError(err) } } fn read_username(path: &str) -> Result<String, ReadUsernameError> { let mut username = String::with_capacity(100); File::open(path)?.read_to_string(&mut username)?; if username.is_empty() { return Err(ReadUsernameError::EmptyUsername(String::from(path))); } Ok(username) } fn main() { //fs::write("config.dat", "").unwrap(); let username = read_username("config.dat"); println!("username or error: {username:?}"); }
关键点:
username
变量可以是Ok(string)
或Err(error)
。- 可以使用
fs::write
调用来测试不同的场景:没有文件、空文件、包含用户名的文件。
对所有不需要是“no_std”的错误类型来说,实现“std::error::Error”是一种很好的做法,而这需要“Debug”和“Display”。“core”的“Error”crate 仅在 nightly 提供,因此尚未与“no_std”完全兼容。
It’s generally helpful for them to implement Clone
and Eq
too where possible, to make life easier for tests and consumers of your library. In this case we can’t easily do so, because io::Error
doesn’t implement them.