Last active
August 28, 2022 19:16
-
-
Save eduardonunesp/c728364b69b6f5227237ddd0baae2ebf to your computer and use it in GitHub Desktop.
CPF Checker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Debug, PartialEq)] | |
enum CPFError { | |
InvalidDigitAtIndex(u32), | |
InvalidLength(u32), | |
Invalid, | |
} | |
fn get_dv(cpf: &Vec<u32>, digit_position: u32) -> u32 { | |
let mut count = digit_position; | |
let mut sum = 0; | |
for n in cpf { | |
if count >= 2 { | |
sum += n * count as u32; | |
count -= 1; | |
} | |
} | |
let res = (sum * 10) % 11; | |
if res == 10 { | |
return 0; | |
} | |
res | |
} | |
fn parse_cpf(raw_cpf: &str) -> Result<Vec<u32>, CPFError> { | |
let mut cpf: Vec<u32> = vec![]; | |
let cpf_chars = raw_cpf | |
.chars() | |
.filter(|s| !"./-".contains(s.to_owned())) | |
.collect::<Vec<_>>(); | |
for (i, char) in cpf_chars.into_iter().enumerate() { | |
if !char.is_digit(10) { | |
return Err(CPFError::InvalidDigitAtIndex(i as u32)); | |
} | |
cpf.push(char.to_digit(10).ok_or_else(|| CPFError::Invalid)?); | |
} | |
if cpf.len() != 11 { | |
return Err(CPFError::InvalidLength(cpf.len() as u32)); | |
} | |
Ok(cpf) | |
} | |
fn check_digits(cpf: &Vec<u32>) -> Result<(), CPFError> { | |
let dv1 = get_dv(cpf, 10); | |
let dv2 = get_dv(cpf, 11); | |
if dv1 == cpf[9] && dv2 == cpf[10] { | |
return Ok(()); | |
} | |
Err(CPFError::Invalid) | |
} | |
fn main() -> Result<(), CPFError> { | |
// Generated at https://www.4devs.com.br/gerador_de_cpf | |
let cpf = "093.519.620-08"; | |
let cpf_vec = parse_cpf(cpf)?; | |
check_digits(&cpf_vec)?; | |
Ok(()) | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
#[test] | |
fn test_parse_cpf() { | |
let cpf = "093.519.620-08"; | |
let cpf_vec = parse_cpf(cpf).unwrap(); | |
assert_eq!(cpf_vec, vec![0, 9, 3, 5, 1, 9, 6, 2, 0, 0, 8]); | |
} | |
#[test] | |
fn test_check_digits() { | |
let cpf = "093.519.620-08"; | |
let cpf_vec = parse_cpf(cpf).unwrap(); | |
assert!(check_digits(&cpf_vec).is_ok()); | |
} | |
#[test] | |
fn test_wrong_size() { | |
let cpf = "093.519.620-0"; | |
let cpf_vec = parse_cpf(cpf); | |
assert_eq!(cpf_vec.err().unwrap(), CPFError::InvalidLength(10)); | |
let cpf = "093.519.620-081"; | |
let cpf_vec = parse_cpf(cpf); | |
assert_eq!(cpf_vec.err().unwrap(), CPFError::InvalidLength(12)); | |
} | |
#[test] | |
fn test_invalid_digit() { | |
let cpf = "093.519.620-0a"; | |
let cpf_vec = parse_cpf(cpf); | |
assert_eq!(cpf_vec.err().unwrap(), CPFError::InvalidDigitAtIndex(10)); | |
} | |
#[test] | |
fn test_invalid_cpf() { | |
let cpf = "093.519.620-09"; | |
let cpf_vec = parse_cpf(cpf).unwrap(); | |
assert_eq!(check_digits(&cpf_vec).err().unwrap(), CPFError::Invalid); | |
} | |
#[test] | |
fn test_some_cpfs() { | |
// Generated at https://www.4devs.com.br/gerador_de_cpf | |
let cpfs = vec![ | |
"709.348.790-44", | |
"332.919.370-07", | |
"243.047.880-35", | |
"569.237.650-48", | |
"453.022.170-90", | |
"127.844.030-50", | |
"420.007.790-69", | |
"236.283.980-02", | |
]; | |
for cpf in cpfs { | |
let cpf_vec = parse_cpf(cpf).unwrap(); | |
assert!(check_digits(&cpf_vec).is_ok()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment