Skip to content

Instantly share code, notes, and snippets.

@eduardonunesp
Last active August 28, 2022 19:16
Show Gist options
  • Save eduardonunesp/c728364b69b6f5227237ddd0baae2ebf to your computer and use it in GitHub Desktop.
Save eduardonunesp/c728364b69b6f5227237ddd0baae2ebf to your computer and use it in GitHub Desktop.
CPF Checker
#[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