commit e43225e2e68bc9b5d32755e77165d1ec2502bbc8
parent 4ed98dc57ed48957f9a44fba1b4f40e480d43b05
Author: Antoine A <>
Date: Fri, 21 Feb 2025 18:28:56 +0100
common: improve iban registry codegen
Diffstat:
2 files changed, 302 insertions(+), 766 deletions(-)
diff --git a/common/taler-common/src/types/iban.rs b/common/taler-common/src/types/iban.rs
@@ -21,7 +21,7 @@ use std::{
};
pub use registry::Country;
-use registry::{IbanC, PatternErr, rng_pattern};
+use registry::{IbanC, PatternErr, check_pattern, rng_pattern};
use super::utils::InlineStr;
@@ -62,11 +62,12 @@ impl IBAN {
}
fn from_raw_parts(country: Country, bban: &[u8]) -> Self {
- // Create a iban with an empty digit check
+ // Create an iban with an empty digit check
let mut encoded = InlineStr::try_from_iter(
country
.as_bytes()
- .into_iter()
+ .iter()
+ .copied()
.chain([b'0', b'0'])
.chain(bban.iter().copied()),
)
@@ -86,8 +87,7 @@ impl IBAN {
}
pub fn from_parts(country: Country, bban: &str) -> Self {
- assert_eq!(bban.len(), country.bban_len()); // TODO return Result ?
- country.bban_check(bban.as_bytes()).unwrap(); // TODO return Result
+ check_pattern(bban.as_bytes(), country.bban_pattern()).unwrap(); // TODO return Result
Self::from_raw_parts(country, bban.as_bytes())
}
@@ -166,7 +166,7 @@ impl FromStr for IBAN {
} else if !IbanC::A.check(&encoded[0..2]) || !IbanC::N.check(&encoded[2..4]) {
Err(IbanErrorKind::Malformed)
} else if let Some(country) = Country::from_str(&encoded.as_ref()[..2]) {
- if let Err(e) = country.bban_check(&encoded[4..]) {
+ if let Err(e) = check_pattern(&encoded[4..], country.bban_pattern()) {
Err(match e {
PatternErr::Len(expected, got) => IbanErrorKind::Size(expected, got),
PatternErr::Malformed => IbanErrorKind::Malformed,
diff --git a/common/taler-common/src/types/iban/registry.rs b/common/taler-common/src/types/iban/registry.rs
@@ -344,97 +344,97 @@ impl Country {
}
}
- pub const fn as_bytes(self) -> [u8; 2] {
+ pub const fn as_bytes(self) -> &'static [u8; 2] {
match self {
- AD => [b'A', b'D'],
- AE => [b'A', b'E'],
- AL => [b'A', b'L'],
- AT => [b'A', b'T'],
- AZ => [b'A', b'Z'],
- BA => [b'B', b'A'],
- BE => [b'B', b'E'],
- BG => [b'B', b'G'],
- BH => [b'B', b'H'],
- BI => [b'B', b'I'],
- BR => [b'B', b'R'],
- BY => [b'B', b'Y'],
- CH => [b'C', b'H'],
- CR => [b'C', b'R'],
- CY => [b'C', b'Y'],
- CZ => [b'C', b'Z'],
- DE => [b'D', b'E'],
- DJ => [b'D', b'J'],
- DK => [b'D', b'K'],
- DO => [b'D', b'O'],
- EE => [b'E', b'E'],
- EG => [b'E', b'G'],
- ES => [b'E', b'S'],
- FI => [b'F', b'I'],
- FK => [b'F', b'K'],
- FO => [b'F', b'O'],
- FR => [b'F', b'R'],
- GB => [b'G', b'B'],
- GE => [b'G', b'E'],
- GI => [b'G', b'I'],
- GL => [b'G', b'L'],
- GR => [b'G', b'R'],
- GT => [b'G', b'T'],
- HN => [b'H', b'N'],
- HR => [b'H', b'R'],
- HU => [b'H', b'U'],
- IE => [b'I', b'E'],
- IL => [b'I', b'L'],
- IQ => [b'I', b'Q'],
- IS => [b'I', b'S'],
- IT => [b'I', b'T'],
- JO => [b'J', b'O'],
- KW => [b'K', b'W'],
- KZ => [b'K', b'Z'],
- LB => [b'L', b'B'],
- LC => [b'L', b'C'],
- LI => [b'L', b'I'],
- LT => [b'L', b'T'],
- LU => [b'L', b'U'],
- LV => [b'L', b'V'],
- LY => [b'L', b'Y'],
- MC => [b'M', b'C'],
- MD => [b'M', b'D'],
- ME => [b'M', b'E'],
- MK => [b'M', b'K'],
- MN => [b'M', b'N'],
- MR => [b'M', b'R'],
- MT => [b'M', b'T'],
- MU => [b'M', b'U'],
- NI => [b'N', b'I'],
- NL => [b'N', b'L'],
- NO => [b'N', b'O'],
- OM => [b'O', b'M'],
- PK => [b'P', b'K'],
- PL => [b'P', b'L'],
- PS => [b'P', b'S'],
- PT => [b'P', b'T'],
- QA => [b'Q', b'A'],
- RO => [b'R', b'O'],
- RS => [b'R', b'S'],
- RU => [b'R', b'U'],
- SA => [b'S', b'A'],
- SC => [b'S', b'C'],
- SD => [b'S', b'D'],
- SE => [b'S', b'E'],
- SI => [b'S', b'I'],
- SK => [b'S', b'K'],
- SM => [b'S', b'M'],
- SO => [b'S', b'O'],
- ST => [b'S', b'T'],
- SV => [b'S', b'V'],
- TL => [b'T', b'L'],
- TN => [b'T', b'N'],
- TR => [b'T', b'R'],
- UA => [b'U', b'A'],
- VA => [b'V', b'A'],
- VG => [b'V', b'G'],
- XK => [b'X', b'K'],
- YE => [b'Y', b'E'],
+ AD => b"AD",
+ AE => b"AE",
+ AL => b"AL",
+ AT => b"AT",
+ AZ => b"AZ",
+ BA => b"BA",
+ BE => b"BE",
+ BG => b"BG",
+ BH => b"BH",
+ BI => b"BI",
+ BR => b"BR",
+ BY => b"BY",
+ CH => b"CH",
+ CR => b"CR",
+ CY => b"CY",
+ CZ => b"CZ",
+ DE => b"DE",
+ DJ => b"DJ",
+ DK => b"DK",
+ DO => b"DO",
+ EE => b"EE",
+ EG => b"EG",
+ ES => b"ES",
+ FI => b"FI",
+ FK => b"FK",
+ FO => b"FO",
+ FR => b"FR",
+ GB => b"GB",
+ GE => b"GE",
+ GI => b"GI",
+ GL => b"GL",
+ GR => b"GR",
+ GT => b"GT",
+ HN => b"HN",
+ HR => b"HR",
+ HU => b"HU",
+ IE => b"IE",
+ IL => b"IL",
+ IQ => b"IQ",
+ IS => b"IS",
+ IT => b"IT",
+ JO => b"JO",
+ KW => b"KW",
+ KZ => b"KZ",
+ LB => b"LB",
+ LC => b"LC",
+ LI => b"LI",
+ LT => b"LT",
+ LU => b"LU",
+ LV => b"LV",
+ LY => b"LY",
+ MC => b"MC",
+ MD => b"MD",
+ ME => b"ME",
+ MK => b"MK",
+ MN => b"MN",
+ MR => b"MR",
+ MT => b"MT",
+ MU => b"MU",
+ NI => b"NI",
+ NL => b"NL",
+ NO => b"NO",
+ OM => b"OM",
+ PK => b"PK",
+ PL => b"PL",
+ PS => b"PS",
+ PT => b"PT",
+ QA => b"QA",
+ RO => b"RO",
+ RS => b"RS",
+ RU => b"RU",
+ SA => b"SA",
+ SC => b"SC",
+ SD => b"SD",
+ SE => b"SE",
+ SI => b"SI",
+ SK => b"SK",
+ SM => b"SM",
+ SO => b"SO",
+ ST => b"ST",
+ SV => b"SV",
+ TL => b"TL",
+ TN => b"TN",
+ TR => b"TR",
+ UA => b"UA",
+ VA => b"VA",
+ VG => b"VG",
+ XK => b"XK",
+ YE => b"YE",
}
}
@@ -818,678 +818,192 @@ impl Country {
}
}
- pub fn bban_check(self, iban_ascii: &[u8]) -> Result<(), PatternErr> {
- // IBAN are made of ASCII digits and uppercase
- debug_assert!(
- iban_ascii
- .iter()
- .all(|b| b.is_ascii_uppercase() || b.is_ascii_digit())
- );
+ pub const fn bank_pattern(self) -> Pattern {
+ match self {
+ AD => &[(4, N)],
+ AE => &[(3, N)],
+ AL => &[(3, N)],
+ AT => &[(5, N)],
+ AZ => &[(4, A)],
+ BA => &[(3, N)],
+ BE => &[(3, N)],
+ BG => &[(4, A)],
+ BH => &[(4, A)],
+ BI => &[(5, N)],
+ BR => &[(8, N)],
+ BY => &[(4, C)],
+ CH => &[(5, N)],
+ CR => &[(4, N)],
+ CY => &[(3, N)],
+ CZ => &[(4, N)],
+ DE => &[(8, N)],
+ DJ => &[(5, N)],
+ DK => &[(4, N)],
+ DO => &[(4, C)],
+ EE => &[(2, N)],
+ EG => &[(4, N)],
+ ES => &[(4, N)],
+ FI => &[(3, N)],
+ FK => &[(2, A)],
+ FO => &[(4, N)],
+ FR => &[(5, N)],
+ GB => &[(4, A)],
+ GE => &[(2, A)],
+ GI => &[(4, A)],
+ GL => &[(4, N)],
+ GR => &[(3, N)],
+ GT => &[(4, C)],
+ HN => &[(4, A)],
+ HR => &[(7, N)],
+ HU => &[(3, N)],
+ IE => &[(4, A)],
+ IL => &[(3, N)],
+ IQ => &[(4, A)],
+ IS => &[(2, N)],
+ IT => &[(5, N)],
+ JO => &[(4, N)],
+ KW => &[(4, A)],
+ KZ => &[(3, N)],
+ LB => &[(4, A)],
+ LC => &[(4, A)],
+ LI => &[(5, N)],
+ LT => &[(5, N)],
+ LU => &[(3, N)],
+ LV => &[(4, A)],
+ LY => &[(3, N)],
+ MC => &[(5, N)],
+ MD => &[(2, C)],
+ ME => &[(3, N)],
+ MK => &[(3, N)],
+ MN => &[(4, N)],
+ MR => &[(5, N)],
+ MT => &[(4, A)],
+ MU => &[(6, C)],
+ NI => &[(4, A)],
+ NL => &[(4, A)],
+ NO => &[(4, N)],
+ OM => &[(3, N)],
+ PK => &[(4, A)],
+ PL => &[],
+ PS => &[(4, A)],
+ PT => &[(4, N)],
+ QA => &[(4, A)],
+ RO => &[(4, A)],
+ RS => &[(3, N)],
+ RU => &[(9, N)],
+ SA => &[(2, N)],
+ SC => &[(4, A), (2, N)],
+ SD => &[(2, N)],
+ SE => &[(3, N)],
+ SI => &[(5, N)],
+ SK => &[(4, N)],
+ SM => &[(5, N)],
+ SO => &[(4, N)],
+ ST => &[(4, N)],
+ SV => &[(4, A)],
+ TL => &[(3, N)],
+ TN => &[(2, N)],
+ TR => &[(5, N)],
+ UA => &[(6, N)],
+ VA => &[(3, N)],
+ VG => &[(4, A)],
+ XK => &[(2, N)],
+ YE => &[(4, A)],
+ }
+ }
+
+ pub const fn branch_pattern(self) -> Pattern {
match self {
- AD => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..8]) || !C.check(&iban_ascii[8..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- AE => {
- if iban_ascii.len() != 19 {
- return Err(PatternErr::Len(19, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..19]) {
- return Err(PatternErr::Malformed);
- }
- }
- AL => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..8]) || !C.check(&iban_ascii[8..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- AT => {
- if iban_ascii.len() != 16 {
- return Err(PatternErr::Len(16, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..16]) {
- return Err(PatternErr::Malformed);
- }
- }
- AZ => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- BA => {
- if iban_ascii.len() != 16 {
- return Err(PatternErr::Len(16, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..16]) {
- return Err(PatternErr::Malformed);
- }
- }
- BE => {
- if iban_ascii.len() != 12 {
- return Err(PatternErr::Len(12, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..12]) {
- return Err(PatternErr::Malformed);
- }
- }
- BG => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4])
- || !N.check(&iban_ascii[4..10])
- || !C.check(&iban_ascii[10..18])
- {
- return Err(PatternErr::Malformed);
- }
- }
- BH => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..18]) {
- return Err(PatternErr::Malformed);
- }
- }
- BI => {
- if iban_ascii.len() != 23 {
- return Err(PatternErr::Len(23, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..23]) {
- return Err(PatternErr::Malformed);
- }
- }
- BR => {
- if iban_ascii.len() != 25 {
- return Err(PatternErr::Len(25, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..23])
- || !A.check(&iban_ascii[23..24])
- || !C.check(&iban_ascii[24..25])
- {
- return Err(PatternErr::Malformed);
- }
- }
- BY => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !C.check(&iban_ascii[0..4])
- || !N.check(&iban_ascii[4..8])
- || !C.check(&iban_ascii[8..24])
- {
- return Err(PatternErr::Malformed);
- }
- }
- CH => {
- if iban_ascii.len() != 17 {
- return Err(PatternErr::Len(17, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..5]) || !C.check(&iban_ascii[5..17]) {
- return Err(PatternErr::Malformed);
- }
- }
- CR => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..18]) {
- return Err(PatternErr::Malformed);
- }
- }
- CY => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..8]) || !C.check(&iban_ascii[8..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- CZ => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- DE => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..18]) {
- return Err(PatternErr::Malformed);
- }
- }
- DJ => {
- if iban_ascii.len() != 23 {
- return Err(PatternErr::Len(23, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..23]) {
- return Err(PatternErr::Malformed);
- }
- }
- DK => {
- if iban_ascii.len() != 14 {
- return Err(PatternErr::Len(14, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..14]) {
- return Err(PatternErr::Malformed);
- }
- }
- DO => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !C.check(&iban_ascii[0..4]) || !N.check(&iban_ascii[4..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- EE => {
- if iban_ascii.len() != 16 {
- return Err(PatternErr::Len(16, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..16]) {
- return Err(PatternErr::Malformed);
- }
- }
- EG => {
- if iban_ascii.len() != 25 {
- return Err(PatternErr::Len(25, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..25]) {
- return Err(PatternErr::Malformed);
- }
- }
- ES => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- FI => {
- if iban_ascii.len() != 14 {
- return Err(PatternErr::Len(14, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..14]) {
- return Err(PatternErr::Malformed);
- }
- }
- FK => {
- if iban_ascii.len() != 14 {
- return Err(PatternErr::Len(14, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..2]) || !N.check(&iban_ascii[2..14]) {
- return Err(PatternErr::Malformed);
- }
- }
- FO => {
- if iban_ascii.len() != 14 {
- return Err(PatternErr::Len(14, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..14]) {
- return Err(PatternErr::Malformed);
- }
- }
- FR => {
- if iban_ascii.len() != 23 {
- return Err(PatternErr::Len(23, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..10])
- || !C.check(&iban_ascii[10..21])
- || !N.check(&iban_ascii[21..23])
- {
- return Err(PatternErr::Malformed);
- }
- }
- GB => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !N.check(&iban_ascii[4..18]) {
- return Err(PatternErr::Malformed);
- }
- }
- GE => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..2]) || !N.check(&iban_ascii[2..18]) {
- return Err(PatternErr::Malformed);
- }
- }
- GI => {
- if iban_ascii.len() != 19 {
- return Err(PatternErr::Len(19, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..19]) {
- return Err(PatternErr::Malformed);
- }
- }
- GL => {
- if iban_ascii.len() != 14 {
- return Err(PatternErr::Len(14, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..14]) {
- return Err(PatternErr::Malformed);
- }
- }
- GR => {
- if iban_ascii.len() != 23 {
- return Err(PatternErr::Len(23, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..7]) || !C.check(&iban_ascii[7..23]) {
- return Err(PatternErr::Malformed);
- }
- }
- GT => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !C.check(&iban_ascii[0..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- HN => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !N.check(&iban_ascii[4..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- HR => {
- if iban_ascii.len() != 17 {
- return Err(PatternErr::Len(17, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..17]) {
- return Err(PatternErr::Malformed);
- }
- }
- HU => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- IE => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !N.check(&iban_ascii[4..18]) {
- return Err(PatternErr::Malformed);
- }
- }
- IL => {
- if iban_ascii.len() != 19 {
- return Err(PatternErr::Len(19, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..19]) {
- return Err(PatternErr::Malformed);
- }
- }
- IQ => {
- if iban_ascii.len() != 19 {
- return Err(PatternErr::Len(19, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !N.check(&iban_ascii[4..19]) {
- return Err(PatternErr::Malformed);
- }
- }
- IS => {
- if iban_ascii.len() != 22 {
- return Err(PatternErr::Len(22, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..22]) {
- return Err(PatternErr::Malformed);
- }
- }
- IT => {
- if iban_ascii.len() != 23 {
- return Err(PatternErr::Len(23, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..1])
- || !N.check(&iban_ascii[1..11])
- || !C.check(&iban_ascii[11..23])
- {
- return Err(PatternErr::Malformed);
- }
- }
- JO => {
- if iban_ascii.len() != 26 {
- return Err(PatternErr::Len(26, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4])
- || !N.check(&iban_ascii[4..8])
- || !C.check(&iban_ascii[8..26])
- {
- return Err(PatternErr::Malformed);
- }
- }
- KW => {
- if iban_ascii.len() != 26 {
- return Err(PatternErr::Len(26, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..26]) {
- return Err(PatternErr::Malformed);
- }
- }
- KZ => {
- if iban_ascii.len() != 16 {
- return Err(PatternErr::Len(16, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..3]) || !C.check(&iban_ascii[3..16]) {
- return Err(PatternErr::Malformed);
- }
- }
- LB => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- LC => {
- if iban_ascii.len() != 28 {
- return Err(PatternErr::Len(28, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..28]) {
- return Err(PatternErr::Malformed);
- }
- }
- LI => {
- if iban_ascii.len() != 17 {
- return Err(PatternErr::Len(17, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..5]) || !C.check(&iban_ascii[5..17]) {
- return Err(PatternErr::Malformed);
- }
- }
- LT => {
- if iban_ascii.len() != 16 {
- return Err(PatternErr::Len(16, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..16]) {
- return Err(PatternErr::Malformed);
- }
- }
- LU => {
- if iban_ascii.len() != 16 {
- return Err(PatternErr::Len(16, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..3]) || !C.check(&iban_ascii[3..16]) {
- return Err(PatternErr::Malformed);
- }
- }
- LV => {
- if iban_ascii.len() != 17 {
- return Err(PatternErr::Len(17, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..17]) {
- return Err(PatternErr::Malformed);
- }
- }
- LY => {
- if iban_ascii.len() != 21 {
- return Err(PatternErr::Len(21, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..21]) {
- return Err(PatternErr::Malformed);
- }
- }
- MC => {
- if iban_ascii.len() != 23 {
- return Err(PatternErr::Len(23, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..10])
- || !C.check(&iban_ascii[10..21])
- || !N.check(&iban_ascii[21..23])
- {
- return Err(PatternErr::Malformed);
- }
- }
- MD => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !C.check(&iban_ascii[0..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- ME => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..18]) {
- return Err(PatternErr::Malformed);
- }
- }
- MK => {
- if iban_ascii.len() != 15 {
- return Err(PatternErr::Len(15, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..3])
- || !C.check(&iban_ascii[3..13])
- || !N.check(&iban_ascii[13..15])
- {
- return Err(PatternErr::Malformed);
- }
- }
- MN => {
- if iban_ascii.len() != 16 {
- return Err(PatternErr::Len(16, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..16]) {
- return Err(PatternErr::Malformed);
- }
- }
- MR => {
- if iban_ascii.len() != 23 {
- return Err(PatternErr::Len(23, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..23]) {
- return Err(PatternErr::Malformed);
- }
- }
- MT => {
- if iban_ascii.len() != 27 {
- return Err(PatternErr::Len(27, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4])
- || !N.check(&iban_ascii[4..9])
- || !C.check(&iban_ascii[9..27])
- {
- return Err(PatternErr::Malformed);
- }
- }
- MU => {
- if iban_ascii.len() != 26 {
- return Err(PatternErr::Len(26, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4])
- || !N.check(&iban_ascii[4..23])
- || !A.check(&iban_ascii[23..26])
- {
- return Err(PatternErr::Malformed);
- }
- }
- NI => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !N.check(&iban_ascii[4..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- NL => {
- if iban_ascii.len() != 14 {
- return Err(PatternErr::Len(14, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !N.check(&iban_ascii[4..14]) {
- return Err(PatternErr::Malformed);
- }
- }
- NO => {
- if iban_ascii.len() != 11 {
- return Err(PatternErr::Len(11, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..11]) {
- return Err(PatternErr::Malformed);
- }
- }
- OM => {
- if iban_ascii.len() != 19 {
- return Err(PatternErr::Len(19, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..3]) || !C.check(&iban_ascii[3..19]) {
- return Err(PatternErr::Malformed);
- }
- }
- PK => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- PL => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- PS => {
- if iban_ascii.len() != 25 {
- return Err(PatternErr::Len(25, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..25]) {
- return Err(PatternErr::Malformed);
- }
- }
- PT => {
- if iban_ascii.len() != 21 {
- return Err(PatternErr::Len(21, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..21]) {
- return Err(PatternErr::Malformed);
- }
- }
- QA => {
- if iban_ascii.len() != 25 {
- return Err(PatternErr::Len(25, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..25]) {
- return Err(PatternErr::Malformed);
- }
- }
- RO => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !C.check(&iban_ascii[4..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- RS => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..18]) {
- return Err(PatternErr::Malformed);
- }
- }
- RU => {
- if iban_ascii.len() != 29 {
- return Err(PatternErr::Len(29, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..14]) || !C.check(&iban_ascii[14..29]) {
- return Err(PatternErr::Malformed);
- }
- }
- SA => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..2]) || !C.check(&iban_ascii[2..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- SC => {
- if iban_ascii.len() != 27 {
- return Err(PatternErr::Len(27, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4])
- || !N.check(&iban_ascii[4..24])
- || !A.check(&iban_ascii[24..27])
- {
- return Err(PatternErr::Malformed);
- }
- }
- SD => {
- if iban_ascii.len() != 14 {
- return Err(PatternErr::Len(14, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..14]) {
- return Err(PatternErr::Malformed);
- }
- }
- SE => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- SI => {
- if iban_ascii.len() != 15 {
- return Err(PatternErr::Len(15, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..15]) {
- return Err(PatternErr::Malformed);
- }
- }
- SK => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- SM => {
- if iban_ascii.len() != 23 {
- return Err(PatternErr::Len(23, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..1])
- || !N.check(&iban_ascii[1..11])
- || !C.check(&iban_ascii[11..23])
- {
- return Err(PatternErr::Malformed);
- }
- }
- SO => {
- if iban_ascii.len() != 19 {
- return Err(PatternErr::Len(19, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..19]) {
- return Err(PatternErr::Malformed);
- }
- }
- ST => {
- if iban_ascii.len() != 21 {
- return Err(PatternErr::Len(21, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..21]) {
- return Err(PatternErr::Malformed);
- }
- }
- SV => {
- if iban_ascii.len() != 24 {
- return Err(PatternErr::Len(24, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !N.check(&iban_ascii[4..24]) {
- return Err(PatternErr::Malformed);
- }
- }
- TL => {
- if iban_ascii.len() != 19 {
- return Err(PatternErr::Len(19, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..19]) {
- return Err(PatternErr::Malformed);
- }
- }
- TN => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- TR => {
- if iban_ascii.len() != 22 {
- return Err(PatternErr::Len(22, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..6]) || !C.check(&iban_ascii[6..22]) {
- return Err(PatternErr::Malformed);
- }
- }
- UA => {
- if iban_ascii.len() != 25 {
- return Err(PatternErr::Len(25, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..6]) || !C.check(&iban_ascii[6..25]) {
- return Err(PatternErr::Malformed);
- }
- }
- VA => {
- if iban_ascii.len() != 18 {
- return Err(PatternErr::Len(18, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..18]) {
- return Err(PatternErr::Malformed);
- }
- }
- VG => {
- if iban_ascii.len() != 20 {
- return Err(PatternErr::Len(20, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4]) || !N.check(&iban_ascii[4..20]) {
- return Err(PatternErr::Malformed);
- }
- }
- XK => {
- if iban_ascii.len() != 16 {
- return Err(PatternErr::Len(16, iban_ascii.len()));
- } else if !N.check(&iban_ascii[0..16]) {
- return Err(PatternErr::Malformed);
- }
- }
- YE => {
- if iban_ascii.len() != 26 {
- return Err(PatternErr::Len(26, iban_ascii.len()));
- } else if !A.check(&iban_ascii[0..4])
- || !N.check(&iban_ascii[4..8])
- || !C.check(&iban_ascii[8..26])
- {
- return Err(PatternErr::Malformed);
- }
- }
+ AD => &[(4, N)],
+ AE => &[],
+ AL => &[(5, N)],
+ AT => &[],
+ AZ => &[],
+ BA => &[(3, N)],
+ BE => &[],
+ BG => &[(4, N)],
+ BH => &[],
+ BI => &[(5, N)],
+ BR => &[(5, N)],
+ BY => &[],
+ CH => &[],
+ CR => &[],
+ CY => &[(5, N)],
+ CZ => &[],
+ DE => &[],
+ DJ => &[(5, N)],
+ DK => &[],
+ DO => &[],
+ EE => &[],
+ EG => &[(4, N)],
+ ES => &[(4, N)],
+ FI => &[],
+ FK => &[],
+ FO => &[],
+ FR => &[],
+ GB => &[(6, N)],
+ GE => &[],
+ GI => &[],
+ GL => &[],
+ GR => &[(4, N)],
+ GT => &[],
+ HN => &[],
+ HR => &[],
+ HU => &[(4, N)],
+ IE => &[(6, N)],
+ IL => &[(3, N)],
+ IQ => &[(3, N)],
+ IS => &[(2, N)],
+ IT => &[(5, N)],
+ JO => &[(4, N)],
+ KW => &[],
+ KZ => &[],
+ LB => &[],
+ LC => &[],
+ LI => &[],
+ LT => &[],
+ LU => &[],
+ LV => &[],
+ LY => &[(3, N)],
+ MC => &[(5, N)],
+ MD => &[],
+ ME => &[],
+ MK => &[],
+ MN => &[],
+ MR => &[(5, N)],
+ MT => &[(5, N)],
+ MU => &[(2, N)],
+ NI => &[],
+ NL => &[],
+ NO => &[],
+ OM => &[],
+ PK => &[],
+ PL => &[(8, N)],
+ PS => &[],
+ PT => &[(4, N)],
+ QA => &[],
+ RO => &[],
+ RS => &[],
+ RU => &[(5, N)],
+ SA => &[],
+ SC => &[(2, N)],
+ SD => &[],
+ SE => &[],
+ SI => &[],
+ SK => &[],
+ SM => &[(5, N)],
+ SO => &[(3, N)],
+ ST => &[(4, N)],
+ SV => &[],
+ TL => &[],
+ TN => &[(3, N)],
+ TR => &[],
+ UA => &[],
+ VA => &[],
+ VG => &[],
+ XK => &[(2, N)],
+ YE => &[(4, N)],
}
- Ok(())
}
}
@@ -1515,6 +1029,28 @@ pub fn rng_pattern(out: &mut [u8], pattern: Pattern) {
}
}
+/// Valid an IBAN slice against a pattern
+pub fn check_pattern(iban_ascii: &[u8], pattern: Pattern) -> Result<(), PatternErr> {
+ // IBAN are made of ASCII digits and uppercase
+ debug_assert!(
+ iban_ascii
+ .iter()
+ .all(|b| b.is_ascii_uppercase() || b.is_ascii_digit())
+ );
+ let pattern_len: u8 = pattern.iter().map(|(len, _)| *len).sum();
+ if iban_ascii.len() != pattern_len as usize {
+ return Err(PatternErr::Len(pattern_len, iban_ascii.len()));
+ }
+ let mut cursor = 0;
+ for (repetition, char) in pattern {
+ if !char.check(&iban_ascii[cursor..cursor + *repetition as usize]) {
+ return Err(PatternErr::Malformed);
+ }
+ cursor += *repetition as usize;
+ }
+ Ok(())
+}
+
#[cfg(test)]
pub const VALID_IBAN: [(&str, Option<&str>); 89] = [
("AD1200012030200359100100", Some("00012030200359100100")),