cpca/
lib.rs

1//! # CPCA - Chinese Province City Area Parser
2//!
3//! 中国省市区地址解析库,从地址字符串中提取省、市、区信息。
4//!
5//! ## 功能特性
6//!
7//! - 从自由文本地址中提取省、市、区
8//! - 支持省份简称(如 "广东" -> "广东省")
9//! - 支持直辖市特殊处理
10//! - 支持不设区的地级市(东莞、中山、儋州、嘉峪关)
11//! - 内置 2025 年最新行政区划数据(3600+ 条记录)
12//!
13//! ## 快速开始
14//!
15//! ```rust
16//! use cpca::AddressParser;
17//!
18//! let parser = AddressParser::new();
19//!
20//! // 解析完整地址
21//! let result = parser.parse("广东省深圳市南山区科技园");
22//! assert_eq!(result.province, Some("广东省".to_string()));
23//! assert_eq!(result.city, Some("深圳市".to_string()));
24//! assert_eq!(result.district, Some("南山区".to_string()));
25//!
26//! // 支持简称
27//! let result = parser.parse("深圳南山科技园");
28//! assert_eq!(result.province, Some("广东省".to_string()));
29//! assert_eq!(result.city, Some("深圳市".to_string()));
30//!
31//! // 标准化地址
32//! let full = parser.normalize("广东", "深圳", None);
33//! assert_eq!(full, "广东省深圳市");
34//! ```
35
36mod data;
37mod error;
38mod parser;
39mod region;
40mod trie;
41
42pub use error::ParseError;
43pub use parser::AddressParser;
44pub use region::{ParsedAddress, Region};
45
46/// 便捷函数:使用全局解析器解析地址
47///
48/// ```rust
49/// let result = cpca::parse("北京市朝阳区");
50/// assert_eq!(result.province, Some("北京市".to_string()));
51/// ```
52pub fn parse(address: &str) -> ParsedAddress {
53    AddressParser::global().parse(address)
54}
55
56/// 便捷函数:标准化地址
57///
58/// ```rust
59/// let full = cpca::normalize("广东", "深圳", Some("南山"));
60/// assert_eq!(full, "广东省深圳市南山区");
61/// ```
62pub fn normalize(
63    province: impl AsRef<str>,
64    city: impl AsRef<str>,
65    district: Option<&str>,
66) -> String {
67    AddressParser::global().normalize(province, city, district)
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn test_parse_full_address() {
76        let parser = AddressParser::new();
77        let result = parser.parse("广东省深圳市南山区科技园路1号");
78
79        assert_eq!(result.province, Some("广东省".to_string()));
80        assert_eq!(result.city, Some("深圳市".to_string()));
81        assert_eq!(result.district, Some("南山区".to_string()));
82        assert_eq!(result.detail, "科技园路1号");
83    }
84
85    #[test]
86    fn test_parse_short_name() {
87        let parser = AddressParser::new();
88        let result = parser.parse("深圳南山科技园");
89
90        assert_eq!(result.province, Some("广东省".to_string()));
91        assert_eq!(result.city, Some("深圳市".to_string()));
92        assert_eq!(result.district, Some("南山区".to_string()));
93    }
94
95    #[test]
96    fn test_parse_municipality() {
97        let parser = AddressParser::new();
98        let result = parser.parse("北京市朝阳区望京");
99
100        assert_eq!(result.province, Some("北京市".to_string()));
101        assert_eq!(result.city, Some("北京市".to_string()));
102        assert_eq!(result.district, Some("朝阳区".to_string()));
103    }
104
105    #[test]
106    fn test_normalize() {
107        let parser = AddressParser::new();
108
109        assert_eq!(
110            parser.normalize("广东", "深圳", Some("南山")),
111            "广东省深圳市南山区"
112        );
113        assert_eq!(parser.normalize("广东省", "深圳市", None), "广东省深圳市");
114        assert_eq!(
115            parser.normalize("北京", "北京", Some("朝阳")),
116            "北京市北京市朝阳区"
117        );
118    }
119}