use crate::error::ParseError;
use crate::config::{Configuration, CountryInfo};
use crate::ParserConfig;
pub fn parse_country_code(text: &str) -> Result<CountryInfo, ParseError> {
parse_country_code_with_config(text, &ParserConfig::default())
}
pub fn parse_country_code_with_config(
text: &str,
_config: &ParserConfig,
) -> Result<CountryInfo, ParseError> {
if text.trim().is_empty() {
return Err(ParseError::invalid_input("输入文本为空"));
}
if text.len() > 1024 {
return Err(ParseError::invalid_input("输入文本过长"));
}
let config_data = Configuration::load()
.map_err(|e| ParseError::config_error(&format!("配置加载失败: {}", e)))?;
match parse_abbreviations(text, &config_data) {
Ok(country_info) => return Ok(country_info),
Err(_) => {},
}
match parse_traditional_chinese_names(text, &config_data) {
Ok(country_info) => return Ok(country_info),
Err(_) => {},
}
match parse_simplified_chinese_names(text, &config_data) {
Ok(country_info) => return Ok(country_info),
Err(_) => {},
}
match parse_english_names(text, &config_data) {
Ok(country_info) => return Ok(country_info),
Err(_) => {},
}
let chars: Vec<char> = text.chars().collect();
for i in 0..chars.len().saturating_sub(2) {
if chars[i].is_alphabetic() && chars[i+1].is_alphabetic() && chars[i+2].is_alphabetic() {
let slice: String = chars[i..i+3].iter().collect();
let slice_upper = slice.to_uppercase();
for country in config_data.get_countries() {
if country.alpha3 == slice_upper {
let mut valid = true;
if i > 0 {
let prev_char = chars[i-1];
if !is_boundary_char(prev_char) && !prev_char.is_numeric() {
valid = false;
}
}
if valid {
return Ok(country.clone());
}
}
}
}
}
for i in 0..chars.len().saturating_sub(1) {
if chars[i].is_alphabetic() && chars[i+1].is_alphabetic() {
let slice: String = chars[i..i+2].iter().collect();
let slice_upper = slice.to_uppercase();
for country in config_data.get_countries() {
if country.alpha2 == slice_upper {
let mut valid = true;
if i > 0 {
let prev_char = chars[i-1];
if !is_boundary_char(prev_char) && !prev_char.is_numeric() {
valid = false;
}
}
if valid {
return Ok(country.clone());
}
}
}
}
}
for country in config_data.get_countries() {
if text.to_uppercase().contains(&country.alpha3) {
let pattern = country.alpha3.to_string();
if let Some(pos) = text.to_uppercase().find(&pattern) {
let start = pos;
let end = pos + pattern.len();
let prev_valid = start == 0 || is_boundary_char(text.chars().nth(start-1).unwrap_or(' '));
let next_valid = end >= text.len() || is_boundary_char(text.chars().nth(end).unwrap_or(' ')) || text.chars().nth(end).unwrap_or(' ').is_numeric();
if prev_valid && next_valid {
return Ok(country.clone());
}
}
}
if text.to_uppercase().contains(&country.alpha2) {
let pattern = country.alpha2.to_string();
if let Some(pos) = text.to_uppercase().find(&pattern) {
let start = pos;
let end = pos + pattern.len();
let prev_valid = start == 0 || is_boundary_char(text.chars().nth(start-1).unwrap_or(' '));
let next_valid = end >= text.len() || is_boundary_char(text.chars().nth(end).unwrap_or(' ')) || text.chars().nth(end).unwrap_or(' ').is_numeric();
if prev_valid && next_valid {
return Ok(country.clone());
}
}
}
}
Err(ParseError::not_found(text))
}
fn parse_abbreviations(
text: &str,
config_data: &Configuration,
) -> Result<CountryInfo, ParseError> {
let processed_text = text.to_lowercase();
for country in config_data.get_countries() {
for abbr in &country.abbreviations {
if processed_text.contains(&abbr.to_lowercase()) {
return Ok(country.clone());
}
}
}
Err(ParseError::not_found(text))
}
fn parse_traditional_chinese_names(
text: &str,
config_data: &Configuration,
) -> Result<CountryInfo, ParseError> {
for country in config_data.get_countries() {
if text.contains(&country.name_zh_tw) {
return Ok(country.clone());
}
}
Err(ParseError::not_found(text))
}
fn parse_simplified_chinese_names(
text: &str,
config_data: &Configuration,
) -> Result<CountryInfo, ParseError> {
for country in config_data.get_countries() {
if text.contains(&country.name_zh_cn) {
return Ok(country.clone());
}
}
Err(ParseError::not_found(text))
}
fn parse_english_names(
text: &str,
config_data: &Configuration,
) -> Result<CountryInfo, ParseError> {
let processed_text = text.to_lowercase();
for country in config_data.get_countries() {
if processed_text.contains(&country.name_en.to_lowercase()) {
return Ok(country.clone());
}
}
Err(ParseError::not_found(text))
}
fn is_boundary_char(c: char) -> bool {
c.is_whitespace() || c == '@' || c == '【' || c == '[' || c == '#' ||
c == ']' || c == '】' || c == ' ' || c == '\t' || c == '\n'
}