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 // Special codes (Ambiente Nacional, SEFAZ Virtual)
56 ("AN", "91"),
57 ("SVRS", "92"),
58 ])
59});
60
61/// Lazy-initialised reverse map from IBGE numeric state code to two-letter UF abbreviation.
62///
63/// # Examples
64///
65/// ```
66/// use fiscal_core::state_codes::IBGE_TO_UF;
67/// assert_eq!(IBGE_TO_UF.get("41"), Some(&"PR"));
68/// ```
69pub static IBGE_TO_UF: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
70 STATE_IBGE_CODES
71 .iter()
72 .map(|(&uf, &code)| (code, uf))
73 .collect()
74});
75
76/// Get the IBGE numeric code for a state abbreviation.
77///
78/// # Errors
79///
80/// Returns [`FiscalError::InvalidStateCode`] if `uf` is not a known
81/// Brazilian state abbreviation.
82pub fn get_state_code(uf: &str) -> Result<&'static str, FiscalError> {
83 STATE_IBGE_CODES
84 .get(uf)
85 .copied()
86 .ok_or_else(|| FiscalError::InvalidStateCode(uf.to_string()))
87}
88
89/// Get the UF abbreviation for an IBGE numeric code.
90///
91/// # Errors
92///
93/// Returns [`FiscalError::InvalidStateCode`] if `code` is not a known
94/// IBGE numeric state code.
95pub fn get_state_by_code(code: &str) -> Result<&'static str, FiscalError> {
96 IBGE_TO_UF
97 .get(code)
98 .copied()
99 .ok_or_else(|| FiscalError::InvalidStateCode(code.to_string()))
100}