pub fn validate_cnpj(cnpj: &str) -> bool {
let digits: Vec<u64> = cnpj.chars()
.filter(|c| c.is_ascii_digit())
.map(|c| (c as u64) - 48)
.collect();
if digits.len() != 14 { return false; }
if digits.windows(2).all(|w| w[0] == w[1]) { return false; }
let check = |d: &[u64], len: usize| -> u64 {
let weights: Vec<u64> = (0..len).rev().map(|i| 2 + (i % 8) as u64).collect();
let sum: u64 = d[..len].iter().zip(weights.iter()).map(|(a, b)| a * b).sum();
let rem = sum % 11;
if rem < 2 { 0 } else { 11 - rem }
};
digits[12] == check(&digits, 12) && digits[13] == check(&digits, 13)
}
pub fn validate_cpf(cpf: &str) -> bool {
let digits: Vec<u64> = cpf.chars()
.filter(|c| c.is_ascii_digit())
.map(|c| (c as u64) - 48)
.collect();
if digits.len() != 11 {
return false;
}
if digits.windows(2).all(|w| w[0] == w[1]) {
return false;
}
let check = |d: &[u64], len: usize| -> u64 {
let sum: u64 = d[..len].iter().enumerate().map(|(i, &v)| v * (len as u64 + 1 - i as u64)).sum();
let rem = sum % 11;
if rem < 2 { 0 } else { 11 - rem }
};
digits[9] == check(&digits, 9) && digits[10] == check(&digits, 10)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cnpj_valido() {
assert!(validate_cnpj("11222333000181"));
assert!(validate_cnpj("11.222.333/0001-81"));
}
#[test]
fn cnpj_invalido() {
assert!(!validate_cnpj("11222333000182")); assert!(!validate_cnpj("00000000000000")); assert!(!validate_cnpj("1234567")); }
#[test]
fn cpf_valido() {
assert!(validate_cpf("52998224725"));
assert!(validate_cpf("529.982.247-25"));
}
#[test]
fn cpf_invalido() {
assert!(!validate_cpf("52998224726")); assert!(!validate_cpf("11111111111")); assert!(!validate_cpf("123456")); }
}