use crate::codes::{SIGN_CODES, VERIFY_CODES};
use std::{error::Error, fmt, str::FromStr, string::ToString};
#[derive(Debug)]
pub struct ParseIcError {
err: String,
}
impl Error for ParseIcError {}
impl fmt::Display for ParseIcError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "身份证错误:{}", self.err)
}
}
#[derive(Debug)]
pub struct IdentityCard {
pub region: String,
pub birthday: String,
pub seq: String,
pub verify: String,
}
impl IdentityCard {
pub fn verify_ic(&self) -> bool {
if self.region.len() != 6 {
return false;
}
if self.birthday.len() != 8 {
return false;
}
if self.seq.len() != 3 {
return false;
}
if self.verify.len() != 1 {
return false;
}
let verify_code = compute_verify_code(&self.region, &self.birthday, &self.seq).to_string();
verify_code.eq(&self.verify)
}
}
impl fmt::Display for IdentityCard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}{}{}{}",
self.region, self.birthday, self.seq, self.verify
)
}
}
impl FromStr for IdentityCard {
type Err = ParseIcError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let ic_number: String = String::from(s);
if ic_number.len() != 18 {
return Err(ParseIcError {
err: "身份证长度必须是18位".to_string(),
});
}
let ic = IdentityCard {
region: ic_number[..6].to_string(),
birthday: ic_number[6..14].to_string(),
seq: ic_number[14..17].to_string(),
verify: ic_number[17..].to_string(),
};
Ok(ic)
}
}
pub fn compute_verify_code(region: &String, birthday: &String, seq: &String) -> char {
let precode = format!("{}{}{}", region, birthday, seq);
let mut sum: i32 = 0;
let mut i = 0;
for c in precode.chars() {
let n: i32 = c.to_string().parse().unwrap();
sum = sum + SIGN_CODES[i] * n;
i = i + 1;
}
VERIFY_CODES[(sum % 11) as usize]
}