Skip to main content

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}