Skip to content

Commit f50c503

Browse files
committed
Minor refactoring in NIF/NIE validation
1 parent 89ec079 commit f50c503

2 files changed

Lines changed: 30 additions & 20 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "spain-vat-id"
33
authors = ["José Aguilera <hello@jsgm.dev>"]
4-
version = "0.1.2"
4+
version = "0.1.3"
55
edition = "2021"
66
description = "Spanish VAT ID numbers validation/verification"
77
license = "MIT"

src/lib.rs

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#[derive(Debug, thiserror::Error)]
22
pub enum Error {
33
#[error("Not valid: The length should be 9, [X/Y/Z] + [7 numbers] + [Check digit]. Got {0} characters.")]
4-
BadLenght(usize),
4+
BadLength(usize),
55
#[error("Not valid: The first character should be a 'X', 'Y' or 'Z'. Got {0}")]
66
NieBadPrefix(char),
77
#[error("Not valid: Char '{0}' at position {1} is not a number")]
@@ -10,35 +10,34 @@ pub enum Error {
1010
InvalidCheckNumber(char, char),
1111
}
1212

13+
const NIF_LETTERS: [char; 23] = [
14+
'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V',
15+
'H', 'L', 'C', 'K', 'E',
16+
];
17+
18+
#[inline]
1319
pub fn check_digit_nif(val: u32) -> char {
1420
// Calculates the check digit based on the remainder.
15-
let letters: [char; 23] = [
16-
'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V',
17-
'H', 'L', 'C', 'K', 'E',
18-
];
1921
let remainder = val % 23;
20-
letters[remainder as usize]
22+
NIF_LETTERS[remainder as usize]
2123
}
2224

2325
pub fn is_valid_nie(v: &str) -> Result<(), Error> {
2426
// Validate a NIE - Número de Identidad de Extranjero (NIE)
2527
// https://es.wikipedia.org/wiki/N%C3%BAmero_de_identidad_de_extranjero
26-
//
27-
// Note that this function only considers a NIE valid under the INT/2058/2008 regulation.
28+
// Only considers validity under INT/2058/2008 regulation.
29+
2830
if v.len() != 9 {
29-
Err(Error::BadLenght(v.len()))?
31+
Err(Error::BadLength(v.len()))?
3032
}
3133

3234
let first_letter = v.chars().next().unwrap().to_ascii_lowercase();
3335

34-
let value = if first_letter == 'x' {
35-
0
36-
} else if first_letter == 'y' {
37-
1
38-
} else if first_letter == 'z' {
39-
2
40-
} else {
41-
Err(Error::NieBadPrefix(first_letter))?
36+
let value = match first_letter {
37+
'x' => 0,
38+
'y' => 1,
39+
'z' => 2,
40+
other => return Err(Error::NieBadPrefix(other)),
4241
};
4342

4443
let numbers = &v[1..v.len()];
@@ -49,10 +48,10 @@ pub fn is_valid_nif(v: &str) -> Result<(), Error> {
4948
// Validate a NIF - Número de Identificación Fiscal (NIF)
5049
// https://es.wikipedia.org/wiki/N%C3%BAmero_de_identificaci%C3%B3n_fiscal
5150
if v.len() != 9 {
52-
Err(Error::BadLenght(v.len()))?
51+
Err(Error::BadLength(v.len()))?
5352
}
5453

55-
let letter = v.chars().last().unwrap();
54+
let letter = v.chars().last().unwrap().to_ascii_uppercase();
5655
let numbers = &v[..v.len() - 1];
5756

5857
for (index, c) in numbers.chars().enumerate() {
@@ -91,8 +90,19 @@ mod tests {
9190
assert_ne!(check_digit_nif(00000000), 'D');
9291
}
9392

93+
#[test]
94+
fn test_valid_nif() {
95+
is_valid_nif("24591177Z").unwrap();
96+
is_valid_nif("21178533h").unwrap();
97+
is_valid_nif("84731432F").unwrap();
98+
is_valid_nif("65553805X").unwrap();
99+
is_valid_nif("97294190g").unwrap();
100+
}
101+
94102
#[test]
95103
fn test_invalid_nif() {
104+
is_valid_nif("").unwrap_err();
105+
is_valid_nif("5393710G ").unwrap_err();
96106
is_valid_nif("53493710G").unwrap_err();
97107
is_valid_nif("6´420582W").unwrap_err();
98108
is_valid_nif("X6725600C").unwrap_err();

0 commit comments

Comments
 (0)