fiscal_core/state_codes.rs
1//! Brazilian state IBGE code lookup tables and helper functions.
2//!
3//! Two static maps are provided:
4//! - [`STATE_IBGE_CODES`] — two-letter UF abbreviation → IBGE numeric `cUF` code.
5//! - [`IBGE_TO_UF`] — IBGE numeric code → two-letter UF abbreviation (reverse).
6//!
7//! Use [`get_state_code`] and [`get_state_by_code`] for ergonomic access
8//! with proper error handling.
9
10use std::collections::HashMap;
11use std::sync::LazyLock;
12
13use crate::FiscalError;
14
15/// Lazy-initialised map from two-letter UF abbreviation to IBGE numeric state code (`cUF`).
16///
17/// Contains all 26 Brazilian states plus the Federal District (DF).
18///
19/// # Examples
20///
21/// ```
22/// use fiscal_core::state_codes::STATE_IBGE_CODES;
23/// assert_eq!(STATE_IBGE_CODES.get("PR"), Some(&"41"));
24/// assert_eq!(STATE_IBGE_CODES.get("SP"), Some(&"35"));
25/// ```
26pub static STATE_IBGE_CODES: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
27 HashMap::from([
28 ("AC", "12"),
29 ("AL", "27"),
30 ("AP", "16"),
31 ("AM", "13"),
32 ("BA", "29"),
33 ("CE", "23"),
34 ("DF", "53"),
35 ("ES", "32"),
36 ("GO", "52"),
37 ("MA", "21"),
38 ("MT", "51"),
39 ("MS", "50"),
40 ("MG", "31"),
41 ("PA", "15"),
42 ("PB", "25"),
43 ("PR", "41"),
44 ("PE", "26"),
45 ("PI", "22"),
46 ("RJ", "33"),
47 ("RN", "24"),
48 ("RS", "43"),
49 ("RO", "11"),
50 ("RR", "14"),
51 ("SC", "42"),
52 ("SP", "35"),
53 ("SE", "28"),
54 ("TO", "17"),
55 ])
56});
57
58/// Lazy-initialised reverse map from IBGE numeric state code to two-letter UF abbreviation.
59///
60/// # Examples
61///
62/// ```
63/// use fiscal_core::state_codes::IBGE_TO_UF;
64/// assert_eq!(IBGE_TO_UF.get("41"), Some(&"PR"));
65/// ```
66pub static IBGE_TO_UF: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
67 STATE_IBGE_CODES
68 .iter()
69 .map(|(&uf, &code)| (code, uf))
70 .collect()
71});
72
73/// Get the IBGE numeric code for a state abbreviation.
74///
75/// # Errors
76///
77/// Returns [`FiscalError::InvalidStateCode`] if `uf` is not a known
78/// Brazilian state abbreviation.
79pub fn get_state_code(uf: &str) -> Result<&'static str, FiscalError> {
80 STATE_IBGE_CODES
81 .get(uf)
82 .copied()
83 .ok_or_else(|| FiscalError::InvalidStateCode(uf.to_string()))
84}
85
86/// Get the UF abbreviation for an IBGE numeric code.
87///
88/// # Errors
89///
90/// Returns [`FiscalError::InvalidStateCode`] if `code` is not a known
91/// IBGE numeric state code.
92pub fn get_state_by_code(code: &str) -> Result<&'static str, FiscalError> {
93 IBGE_TO_UF
94 .get(code)
95 .copied()
96 .ok_or_else(|| FiscalError::InvalidStateCode(code.to_string()))
97}