Full example

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

fn main() -> Result<(), Box<dyn Error>> {
    let car = CarBuilder::new()
        .number_of_doors(3)?
        .color(Color::Red)
        .has_chromed_exhaust(true)
        .build()?;

    println!("car = {:?}", car);

    Ok(())
}

#[derive(Debug)]
struct Car {
    number_of_doors: usize,
    color: Color,
    horsepower: usize,
    has_chromed_exhaust: bool,
}

struct CarBuilder {
    number_of_doors: usize,
    color: Option<Color>,
    horsepower: usize,
    has_chromed_exhaust: bool,
}

impl CarBuilder {
    pub fn new() -> Self {
        Self {
            number_of_doors: 5,
            color: None,
            horsepower: 45,
            has_chromed_exhaust: false,
        }
    }

    pub fn build(self) -> Result<Car, CarBuilderError> {
        let color = match self.color {
            Some(color) => color,
            None => return Err(CarBuilderError::NoColor),
        };

        Ok(Car {
            number_of_doors: self.number_of_doors,
            color,
            horsepower: self.horsepower,
            has_chromed_exhaust: self.has_chromed_exhaust,
        })
    }

    pub fn number_of_doors(mut self, number_of_doors: usize) -> Result<Self, CarBuilderError> {
        if number_of_doors == 0 {
            Err(CarBuilderError::WrongNumberOfDoors)
        } else {
            self.number_of_doors = number_of_doors;
            Ok(self)
        }
    }

    pub fn color(mut self, color: Color) -> Self {
        self.color = Some(color);
        self
    }

    pub fn horsepower(mut self, value: usize) -> Self {
        self.horsepower = value;
        self
    }

    pub fn has_chromed_exhaust(mut self, value: bool) -> Self {
        self.has_chromed_exhaust = value;
        self
    }
}

#[derive(Debug)]
enum Color {
    Red,
    Green,
}

#[derive(Debug)]
enum CarBuilderError {
    WrongNumberOfDoors,
    NoColor,
}

impl Error for CarBuilderError {
    fn description(&self) -> &str {
        match self {
            CarBuilderError::WrongNumberOfDoors => "A car must have at least one door.",
            CarBuilderError::NoColor => "A car must have a color.",
        }
    }
}

impl fmt::Display for CarBuilderError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}