letterbomb 5.0.0

A fork of the classic Wii hacking tool from fail0verflow
Documentation
use thiserror::Error;

use std::fmt::Display;
use std::str::FromStr;

const TEMPLATE_U: &[u8] = include_bytes!("../include/U.bin");
const TEMPLATE_E: &[u8] = include_bytes!("../include/E.bin");
const TEMPLATE_J: &[u8] = include_bytes!("../include/J.bin");
const TEMPLATE_K: &[u8] = include_bytes!("../include/K.bin");

#[derive(Debug, Error)]
pub enum RegionError {
    #[error("region {0:?} not U, E, J, K")]
    InvalidRegion(String),
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum Region {
    U,
    E,
    J,
    K,
}

impl Region {
    pub fn template_for(&self) -> &'static [u8] {
        match self {
            Region::U => TEMPLATE_U,
            Region::E => TEMPLATE_E,
            Region::J => TEMPLATE_J,
            Region::K => TEMPLATE_K,
        }
    }
}

impl Display for Region {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Region::U => "U",
                Region::E => "E",
                Region::J => "J",
                Region::K => "K",
            }
        )
    }
}

impl FromStr for Region {
    type Err = RegionError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let su: String = s.to_ascii_uppercase().to_owned();
        match su.as_str() {
            "U" | "US" | "UNITED STATES" | "UNITED STATES OF AMERICA" => Ok(Region::U),
            "E" | "EUROPE" => Ok(Region::E),
            "J" | "JAPAN" => Ok(Region::J),
            "K" | "KOREA" => Ok(Region::K),
            _ => Err(RegionError::InvalidRegion(s.to_owned())),
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::region::Region;

    #[test]
    fn region_from_str_ok() {
        assert!(matches!("u".parse::<Region>(), Ok(Region::U)));
        assert!(matches!("United States".parse::<Region>(), Ok(Region::U)));
        assert!(matches!("E".parse::<Region>(), Ok(Region::E)));
        assert!(matches!("jApAn".parse::<Region>(), Ok(Region::J)));
        assert!(matches!("korea".parse::<Region>(), Ok(Region::K)));
    }

    #[test]
    fn region_from_str_err() {
        assert!("x".parse::<Region>().is_err());
    }

    #[test]
    fn region_template_ok() {
        assert!(Region::U.template_for().len() > 100);
        assert!(Region::E.template_for().len() > 100);
        assert!(Region::J.template_for().len() > 100);
        assert!(Region::K.template_for().len() > 100);
    }
}