arscode 0.2.0

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

#[derive(Debug, Error)]
pub enum ARSCodeError {
    #[error("Invalid ARS part land: {land}")]
    InvalidPartLand { land: u8 },
    #[error("Invalid ARS part district: {district}")]
    InvalidPartDistrict { district: u8 },
    #[error("Invalid ARS part county: {county}")]
    InvalidPartCounty { county: u8 },
    #[error("Invalid ARS part vg1: {vg1}")]
    InvalidPartVG1 { vg1: u8 },
    #[error("Invalid ARS part vg2: {vg2}")]
    InvalidPartVG2 { vg2: u8 },
    #[error("Invalid ARS part Municipality: {municipality}")]
    InvalidPartMunicipality { municipality: u16 },
    #[error(
        "Invalid ARS code length for code {erroneous_code}. Expected 9 or 12, got {erroneous_code_length}"
    )]
    InvalidCodeLength {
        erroneous_code: String,
        erroneous_code_length: usize,
    },
    #[error("Parsing error of value {value}, expected {expected}")]
    ParsingError {
        value: String,
        expected: &'static str,
    },
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_invalid_part_land_error() {
        let error = ARSCodeError::InvalidPartLand { land: 20 };
        let message = error.to_string();
        assert!(message.contains("Invalid ARS part land"));
        assert!(message.contains("20"));
    }

    #[test]
    fn test_invalid_part_district_error() {
        let error = ARSCodeError::InvalidPartDistrict { district: 15 };
        let message = error.to_string();
        assert!(message.contains("Invalid ARS part district"));
        assert!(message.contains("15"));
    }

    #[test]
    fn test_invalid_part_county_error() {
        let error = ARSCodeError::InvalidPartCounty { county: 150 };
        let message = error.to_string();
        assert!(message.contains("Invalid ARS part county"));
        assert!(message.contains("150"));
    }

    #[test]
    fn test_invalid_part_vg1_error() {
        let error = ARSCodeError::InvalidPartVG1 { vg1: 100 };
        let message = error.to_string();
        assert!(message.contains("Invalid ARS part vg1"));
        assert!(message.contains("100"));
    }

    #[test]
    fn test_invalid_part_vg2_error() {
        let error = ARSCodeError::InvalidPartVG2 { vg2: 100 };
        let message = error.to_string();
        assert!(message.contains("Invalid ARS part vg2"));
        assert!(message.contains("100"));
    }

    #[test]
    fn test_invalid_part_municipality_error() {
        let error = ARSCodeError::InvalidPartMunicipality { municipality: 5000 };
        let message = error.to_string();
        assert!(message.contains("Invalid ARS part Municipality"));
        assert!(message.contains("5000"));
    }

    #[test]
    fn test_invalid_code_length_error() {
        let error = ARSCodeError::InvalidCodeLength {
            erroneous_code: "12345".to_string(),
            erroneous_code_length: 5,
        };
        let message = error.to_string();
        assert!(message.contains("Invalid ARS code length"));
        assert!(message.contains("12345"));
        assert!(message.contains("5"));
    }

    #[test]
    fn test_parsing_error() {
        let error = ARSCodeError::ParsingError {
            value: "ABC".to_string(),
            expected: "u8",
        };
        let message = error.to_string();
        assert!(message.contains("Parsing error"));
        assert!(message.contains("ABC"));
        assert!(message.contains("u8"));
    }

    #[test]
    fn test_error_debug() {
        let error = ARSCodeError::InvalidPartLand { land: 25 };
        let debug_str = format!("{:?}", error);
        assert!(debug_str.contains("InvalidPartLand"));
        assert!(debug_str.contains("25"));
    }
}