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);
}
}