arscode 0.2.0

Working with the German Amtlicher Regionalschlüssel (ARS): parse, validate and manipulate ARS codes.
Documentation
use std::fmt::Display;

use crate::ARSCode;

/// Represents the 16 federal states of Germany and Germany as a whole.
///
/// Each variant corresponds to a German federal state (Bundesland) with an associated ARS code value.
/// The enum implements `Display` for human-readable names in both English (feature `lang_en`) and German (feature `lang_de`).
///
/// # Examples
///
/// ```
/// use arscode::FederalState;
///
/// let state = FederalState::Bavaria;
/// println!("{}", state); // Prints "Bavaria" or "Bayern" depending on feature
/// ```
///
/// # Variants
///
/// Each variant is assigned a numeric value (0-16) corresponding to its ARS code.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FederalState {
    Germany = 0,
    SchleswigHolstein = 1,
    Hamburg = 2,
    LowerSaxony = 3,
    Bremen = 4,
    NorthRhineWestphalia = 5,
    Hesse = 6,
    RhinelandPalatinate = 7,
    BadenWürttemberg = 8,
    Bavaria = 9,
    Saarland = 10,
    Berlin = 11,
    Brandenburg = 12,
    MecklenburgVorpommern = 13,
    Saxony = 14,
    SaxonyAnhalt = 15,
    Thuringia = 16,
}

impl FederalState {
    /// Checks if the given ARS code belongs to this federal state.
    ///
    /// # Arguments
    ///
    /// * `ars_code` - The ARS code to check
    ///
    /// # Returns
    ///
    /// `true` if the ARS code's state component matches this state, `false` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use arscode::{FederalState, ARSCode};
    ///
    /// let state = FederalState::Berlin;
    /// let ars = ARSCode::new(11, 1, 2, 3, 4, 0).unwrap();
    /// assert!(state.is_state(ars));
    /// ```
    pub fn is_state(&self, ars_code: ARSCode) -> bool {
        ars_code.l() == *self as u8
    }
}

#[cfg(feature = "lang_en")]
impl Display for FederalState {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            FederalState::Germany => write!(f, "Germany"),
            FederalState::SchleswigHolstein => write!(f, "Schleswig-Holstein"),
            FederalState::Hamburg => write!(f, "Hamburg"),
            FederalState::LowerSaxony => write!(f, "Lower-Saxony"),
            FederalState::Bremen => write!(f, "Bremen"),
            FederalState::NorthRhineWestphalia => write!(f, "North-Rhine-Westphalia"),
            FederalState::Hesse => write!(f, "Hesse"),
            FederalState::RhinelandPalatinate => write!(f, "Rhineland-Palatinate"),
            FederalState::BadenWürttemberg => write!(f, "Baden-Württemberg"),
            FederalState::Bavaria => write!(f, "Bavaria"),
            FederalState::Saarland => write!(f, "Saarland"),
            FederalState::Berlin => write!(f, "Berlin"),
            FederalState::Brandenburg => write!(f, "Brandenburg"),
            FederalState::MecklenburgVorpommern => write!(f, "Mecklenburg-Vorpommern"),
            FederalState::Saxony => write!(f, "Saxony"),
            FederalState::SaxonyAnhalt => write!(f, "Saxony-Anhalt"),
            FederalState::Thuringia => write!(f, "Thuringia"),
        }
    }
}

#[cfg(feature = "lang_de")]
impl Display for FederalState {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            FederalState::Germany => write!(f, "Deutschland"),
            FederalState::SchleswigHolstein => write!(f, "Schleswig-Holstein"),
            FederalState::Hamburg => write!(f, "Hamburg"),
            FederalState::LowerSaxony => write!(f, "Niedersachsen"),
            FederalState::Bremen => write!(f, "Bremen"),
            FederalState::NorthRhineWestphalia => write!(f, "Nordrhein-Westfalen"),
            FederalState::Hesse => write!(f, "Hessen"),
            FederalState::RhinelandPalatinate => write!(f, "Rheinland-Pfalz"),
            FederalState::BadenWürttemberg => write!(f, "Baden-Württemberg"),
            FederalState::Bavaria => write!(f, "Bayern"),
            FederalState::Saarland => write!(f, "Saarland"),
            FederalState::Berlin => write!(f, "Berlin"),
            FederalState::Brandenburg => write!(f, "Brandenburg"),
            FederalState::MecklenburgVorpommern => write!(f, "Mecklenburg-Vorpommern"),
            FederalState::Saxony => write!(f, "Sachsen"),
            FederalState::SaxonyAnhalt => write!(f, "Sachsen-Anhalt"),
            FederalState::Thuringia => write!(f, "Thüringen"),
        }
    }
}

/// Converts an ARS code into its corresponding federal state.
///
/// Extracts the state component (first two digit) from the ARS code and returns the corresponding variant.
///
/// # Examples
///
/// ```
/// use arscode::{FederalState, ARSCode};
///
/// let ars = ARSCode::new(5, 1, 2, 3, 4, 0).unwrap();
/// let state = FederalState::from(ars);
/// assert_eq!(state as u8, 5);
/// ```
impl From<ARSCode> for FederalState {
    fn from(value: ARSCode) -> Self {
        match value.l() {
            0 => Self::Germany,
            1 => Self::SchleswigHolstein,
            2 => Self::Hamburg,
            3 => Self::LowerSaxony,
            4 => Self::Bremen,
            5 => Self::NorthRhineWestphalia,
            6 => Self::Hesse,
            7 => Self::RhinelandPalatinate,
            8 => Self::BadenWürttemberg,
            9 => Self::Bavaria,
            10 => Self::Saarland,
            11 => Self::Berlin,
            12 => Self::Brandenburg,
            13 => Self::MecklenburgVorpommern,
            14 => Self::Saxony,
            15 => Self::SaxonyAnhalt,
            16 => Self::Thuringia,

            _ => unreachable!(),
        }
    }
}

/// Converts a federal state into its ARS code numeric value.
///
/// # Examples
///
/// ```
/// use arscode::FederalState;
///
/// let state = FederalState::Hamburg;
/// let code: u8 = state.into();
/// assert_eq!(code, 2);
/// ```
impl From<FederalState> for u8 {
    fn from(value: FederalState) -> Self {
        value as u8
    }
}

/// Converts a federal state into its ARS value.
///
/// # Examples
///
/// ```
/// use arscode::{ARSCode, FederalState};
///
/// let state = FederalState::Hamburg;
/// let code: ARSCode = state.into();
/// assert_eq!(code, ARSCode::new(2, 0, 0, 0, 0, 0).unwrap());
/// ```
impl From<FederalState> for ARSCode {
    fn from(value: FederalState) -> Self {
        ARSCode::new(value.into(), 0, 0, 0, 0, 0).unwrap()
    }
}

#[cfg(test)]
mod tests {
    use crate::{ARSCode, FederalState};

    #[test]
    fn test_ars_is_federal_state() {
        assert!(FederalState::Germany.is_state(ARSCode::new(0, 0, 0, 0, 0, 0).unwrap()));
        assert!(FederalState::SchleswigHolstein.is_state(ARSCode::new(1, 1, 2, 3, 4, 0).unwrap()));
        assert!(FederalState::Hamburg.is_state(ARSCode::new(2, 1, 2, 3, 4, 0).unwrap()));
        assert!(FederalState::LowerSaxony.is_state(ARSCode::new(3, 1, 2, 3, 4, 0).unwrap()));
        assert!(FederalState::Bremen.is_state(ARSCode::new(4, 1, 2, 3, 4, 0).unwrap()));
        assert!(
            FederalState::NorthRhineWestphalia.is_state(ARSCode::new(5, 1, 2, 3, 4, 0).unwrap())
        );
        assert!(FederalState::Hesse.is_state(ARSCode::new(6, 1, 2, 3, 4, 0).unwrap()));
        assert!(
            FederalState::RhinelandPalatinate.is_state(ARSCode::new(7, 1, 2, 3, 4, 0).unwrap())
        );
        assert!(FederalState::BadenWürttemberg.is_state(ARSCode::new(8, 1, 2, 3, 4, 0).unwrap()));
        assert!(FederalState::Bavaria.is_state(ARSCode::new(9, 1, 2, 3, 4, 0).unwrap()));
        assert!(FederalState::Saarland.is_state(ARSCode::new(10, 1, 2, 3, 4, 0).unwrap()));
        assert!(FederalState::Berlin.is_state(ARSCode::new(11, 1, 2, 3, 4, 0).unwrap()));
        assert!(FederalState::Brandenburg.is_state(ARSCode::new(12, 1, 2, 3, 4, 0).unwrap()));
        assert!(
            FederalState::MecklenburgVorpommern.is_state(ARSCode::new(13, 1, 2, 3, 4, 0).unwrap())
        );
        assert!(FederalState::Saxony.is_state(ARSCode::new(14, 1, 2, 3, 4, 0).unwrap()));
        assert!(FederalState::SaxonyAnhalt.is_state(ARSCode::new(15, 1, 2, 3, 4, 0).unwrap()));
        assert!(FederalState::Thuringia.is_state(ARSCode::new(16, 1, 2, 3, 4, 0).unwrap()));
    }
}