Conversión de Tipos de Errores
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:?}"); }
Puntos clave:
- La variable
username
puede serOk(string)
oErr(error)
. - Utiliza la llamada a
fs::write
para probar las distintas situaciones: sin archivo, archivo vacío o archivo con nombre de usuario.
Se recomienda que todos los tipos de errores que no necesitan ser no_std
implementen std::error::Error
, que requiere Debug
y Display
. El crate Error
para core
solo está disponible en nightly, por lo que aún no es totalmente compatible con no_std
.
Por lo general, es útil que también implementen Clone
y Eq
, siempre que sea posible, para facilitar las cosas a las pruebas y a los consumidores de tu biblioteca. En este caso, no podemos hacerlo de forma sencilla porque io::Error
no los implementa.