Poner errores en un Box

Una forma de escribir código simple conservando los errores originales es Box. El inconveniente es que el tipo de error subyacente solo se conoce en tiempo de ejecución y no es determinado estáticamente.

La biblioteca estándar ayuda a poner nuestros errores en un Box al hacer que Box implemente la conversión de cualquier tipo que implemente el rasgo Error en el objeto de rasgo Box<Error>, a través de From.

use std::error;
use std::fmt;

// Cambie el alias a `Box<error::Error>`.
type Result<T> = std::result::Result<T, Box<dyn error::Error>>;

#[derive(Debug, Clone)]
struct VecVacio;

impl fmt::Display for VecVacio {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "primer elemento inválido para duplicar")
    }
}

impl error::Error for VecVacio {}

fn duplica_primer_elemento(vec: Vec<&str>) -> Result<i32> {
    vec.first()
        .ok_or_else(|| VecVacio.into()) // Convierte a Box
        .and_then(|s| {
            s.parse::<i32>()
                .map_err(|e| e.into()) // Convierte a Box
                .map(|i| 2 * i)
        })
}

fn imprime(result: Result<i32>) {
    match result {
        Ok(n) => println!("El doble del primer elemento es {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    let numeros = vec!["42", "93", "18"];
    let vacio = vec![];
    let cadenas = vec!["tofu", "93", "18"];

    imprime(duplica_primer_elemento(numeros));
    imprime(duplica_primer_elemento(vacio));
    imprime(duplica_primer_elemento(cadenas));
}

Ve también

determinado estáticamente y rasgo Error