Convertendo Tipos de Erro
use std::error::Error; use std::fmt::{self, Display, Formatter}; use std::fs::{self, File}; use std::io::{self, Read}; #[derive(Debug)] enum LerNomeUsuarioErro { ErroEs(io::Error), NomeUsuarioVazio(String), } impl Error for LerNomeUsuarioErro {} impl Display for LerNomeUsuarioErro { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { Self::ErroEs(e) => write!(f, "Erro E/S: {e}"), Self::NomeUsuarioVazio(nome_arquivo) => write!(f, "Nome de usuário não encontrado em {nome_arquivo}"), } } } impl From<io::Error> for LerNomeUsuarioErro { fn from(err: io::Error) -> LerNomeUsuarioErro { LerNomeUsuarioErro::ErroEs(err) } } fn ler_nome_usuario(caminho: &str) -> Result<String, LerNomeUsuarioErro> { let mut nome_usuario = String::with_capacity(100); File::open(caminho)?.read_to_string(&mut nome_usuario)?; if nome_usuario.is_empty() { return Err(LerNomeUsuarioErro::NomeUsuarioVazio(String::from(caminho))); } Ok(nome_usuario) } fn main() { //fs::write("config.dat", "").unwrap(); let nome_usuario = ler_nome_usuario("config.dat"); println!("nome_usuario ou erro: {nome_usuario:?}"); }
Pontos chave:
- A variável
nome_usuario
pode serOk(string)
ouErr(error)
. - Use a chamada
fs::write
para testar os diferentes cenários: nenhum arquivo, arquivo vazio e arquivo com nome de usuário.
É uma boa prática para todos os tipos de erro que não precisam ser no_std
implementar std::error::Error
, que requer Debug
e Display
. O crate Error
para core
só está disponível em nightly, então ainda não é totalmente compatível com no_std
.
Geralmente é útil para eles implementar Clone
e Eq
também quando possível, para tornar mais fácil a vida para testes e consumidores da sua biblioteca. Neste caso, não podemos fazê-lo facilmente, porque io::Error
não os implementa.