wonfy-tools 0.2.0

Collection of tools for personal use, provides library and CLI.
Documentation
#[derive(Debug)]
pub struct UnknownError {
    pub name: String,
    pub value: String,
    pub expected: Vec<(Vec<String>, String)>,
}

impl std::fmt::Display for UnknownError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Unknown {} variant {}. \nexpected: ",
            self.name, self.value
        )?;

        for (items, name) in self.expected.iter() {
            write!(f, "\n- ")?;

            for (index, item) in items.iter().enumerate() {
                write!(
                    f,
                    "{}{}",
                    item,
                    if index == items.len() - 1 { "" } else { " | " }
                )?;
            }

            write!(f, " => {}.", name)?;
        }

        Ok(())
    }
}

impl std::error::Error for UnknownError {}

#[derive(Debug)]
pub struct MissingFieldError(pub String);

impl std::fmt::Display for MissingFieldError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Did not set the field \"{}\" when building", self.0)
    }
}

impl std::error::Error for MissingFieldError {}

#[derive(Debug)]
pub enum StitchError {
    MissingField(MissingFieldError),
    NotEnoughImages(usize),
    InvalidWindowSize,
    ImageTooSmall {
        width: u32,
        height: u32,
        window_size: u32,
        crop: u32,
    },
    ScoreOverflow {
        window_size: u32,
        max_width: u32,
    },
    NoAdapter(String),
    Gpu(String),
    NoCandidates,
}

impl std::fmt::Display for StitchError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::MissingField(err) => err.fmt(f),
            Self::NotEnoughImages(count) => {
                write!(f, "Need at least two images to stitch, got {count}")
            }
            Self::InvalidWindowSize => write!(f, "Window size must be at least 1"),
            Self::ImageTooSmall {
                width,
                height,
                window_size,
                crop,
            } => write!(
                f,
                "Image of size {width}x{height} is too small for window size {window_size} with crop {crop}"
            ),
            Self::ScoreOverflow {
                window_size,
                max_width,
            } => write!(
                f,
                "Window size {window_size} with image width {max_width} would overflow the score accumulator, use a smaller window"
            ),
            Self::NoAdapter(details) => write!(
                f,
                "No compatible GPU adapter found (WebGPU/DX12/Vulkan/Metal required): {details}"
            ),
            Self::Gpu(details) => write!(f, "GPU error: {details}"),
            Self::NoCandidates => write!(
                f,
                "No overlap candidates to score, images do not leave room for the search window"
            ),
        }
    }
}

impl std::error::Error for StitchError {}

impl From<MissingFieldError> for StitchError {
    fn from(err: MissingFieldError) -> Self {
        Self::MissingField(err)
    }
}

macro_rules! unknown_error_expected {
    ($($head:literal $(| $tail:literal)* => $type:literal),*) => {
        vec![
            $(
                (
                    vec![$head.to_string() $(, $tail.to_string())*],
                    $type.to_string()
                )
            ),*
        ]
    };
}

pub(crate) use unknown_error_expected;