use core::fmt;
use core::str::FromStr;
use crate::error::ParseSubdivisionError;
use crate::one::Alpha2;
use super::generated::Category;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Subdivision {
pub parent: Alpha2,
pub code: &'static str,
pub name: &'static str,
pub language: &'static str,
pub parent_subdivision: Option<&'static str>,
pub category: Category,
pub local_variant: Option<&'static str>,
}
impl Subdivision {
pub fn try_from_str(s: &str) -> Result<&'static Self, ParseSubdivisionError> {
let bytes = s.as_bytes();
if bytes.len() < 4 || bytes.len() > 6 {
return Err(ParseSubdivisionError::InvalidLength { got: bytes.len() });
}
if !bytes.iter().all(u8::is_ascii) {
return Err(ParseSubdivisionError::NonAscii);
}
if bytes[2] != b'-' {
return Err(ParseSubdivisionError::MissingSeparator);
}
let mut upper = [0u8; 6];
for (i, &b) in bytes.iter().enumerate() {
upper[i] = b.to_ascii_uppercase();
}
let key = core::str::from_utf8(&upper[..bytes.len()])
.map_err(|_| ParseSubdivisionError::NonAscii)?;
Alpha2::try_from_bytes(&upper[..2]).map_err(|_| ParseSubdivisionError::InvalidParent)?;
let idx = super::SUBDIVISION_BY_CODE
.get(key)
.copied()
.ok_or(ParseSubdivisionError::UnknownSubdivision)?;
Ok(&super::ALL_SUBDIVISIONS[idx])
}
}
impl fmt::Display for Subdivision {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.code)
}
}
impl FromStr for Subdivision {
type Err = ParseSubdivisionError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from_str(s).copied()
}
}
impl TryFrom<&str> for Subdivision {
type Error = ParseSubdivisionError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
Self::try_from_str(s).copied()
}
}
impl AsRef<str> for Subdivision {
fn as_ref(&self) -> &str {
self.code
}
}