diff --git a/iban_validation_polars/src/expression.rs b/iban_validation_polars/src/expression.rs index 04597f2..364fe65 100644 --- a/iban_validation_polars/src/expression.rs +++ b/iban_validation_polars/src/expression.rs @@ -1,6 +1,6 @@ +use iban_validation_rs; use polars::prelude::*; use pyo3_polars::derive::polars_expr; -use iban_validation_rs; fn process_iban_str_str(value: &str, iban_valid: &mut String) { *iban_valid = String::from(""); @@ -9,15 +9,27 @@ fn process_iban_str_str(value: &str, iban_valid: &mut String) { Ok(valid_iban) => { iban_valid.push_str(valid_iban.get_iban()); iban_valid.push_str(","); - iban_valid.push_str(valid_iban.iban_bank_id.map(|x| x.to_string()).unwrap_or(String::from("")).as_str()); + iban_valid.push_str( + valid_iban + .iban_bank_id + .map(|x| x.to_string()) + .unwrap_or(String::from("")) + .as_str(), + ); iban_valid.push_str(","); - iban_valid.push_str(valid_iban.iban_branch_id.map(|x| x.to_string()).unwrap_or(String::from("")).as_str()); + iban_valid.push_str( + valid_iban + .iban_branch_id + .map(|x| x.to_string()) + .unwrap_or(String::from("")) + .as_str(), + ); } Err(_) => { - *iban_valid = String::from(""); - } + *iban_valid = String::from(""); } } +} #[polars_expr(output_type=String)] fn process_ibans(inputs: &[Series]) -> PolarsResult { @@ -25,5 +37,3 @@ fn process_ibans(inputs: &[Series]) -> PolarsResult { let out: StringChunked = ca.apply_into_string_amortized(process_iban_str_str); Ok(out.into_series()) } - - diff --git a/iban_validation_py/src/lib.rs b/iban_validation_py/src/lib.rs index 9494f6a..5e529bf 100644 --- a/iban_validation_py/src/lib.rs +++ b/iban_validation_py/src/lib.rs @@ -6,7 +6,7 @@ use pyo3::prelude::*; fn validate_iban(iban_t: &str) -> PyResult { match iban_validation_rs::validate_iban_str(iban_t) { Ok(_) => Ok(true), - Err(_) => Ok(false) + Err(_) => Ok(false), } } diff --git a/iban_validation_rs/benches/speed_bench.rs b/iban_validation_rs/benches/speed_bench.rs index aada6e6..d6d1ee5 100644 --- a/iban_validation_rs/benches/speed_bench.rs +++ b/iban_validation_rs/benches/speed_bench.rs @@ -2,8 +2,9 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use iban_validation_rs::validate_iban_str; pub fn valid_001(c: &mut Criterion) { - c.bench_function("valid 001", |b| b.iter(|| - validate_iban_str(black_box("DE44500105175407324931")))); + c.bench_function("valid 001", |b| { + b.iter(|| validate_iban_str(black_box("DE44500105175407324931"))) + }); } pub fn valid_002(c: &mut Criterion) { @@ -111,15 +112,14 @@ pub fn valid_002(c: &mut Criterion) { "DE89370400440532013000", ]; - c.bench_function("valid 002", |b| b.iter(|| - { + c.bench_function("valid 002", |b| { + b.iter(|| { for iban in &tc { let _ = validate_iban_str(black_box(iban)); } - } - )); - + }) + }); } criterion_group!(benches, valid_001, valid_002); -criterion_main!(benches); \ No newline at end of file +criterion_main!(benches); diff --git a/iban_validation_rs/src/lib.rs b/iban_validation_rs/src/lib.rs index 65fb1d6..b30e102 100644 --- a/iban_validation_rs/src/lib.rs +++ b/iban_validation_rs/src/lib.rs @@ -4,12 +4,11 @@ use std::error::Error; use std::fmt; use std::sync::LazyLock; - /// indicate which information is expected from the Iban Registry and in the record. #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct IbanFields { - /// two-letter country codes as per ISO 3166-1 - pub ctry_cd: [u8;2], + /// two-letter country codes as per ISO 3166-1 + pub ctry_cd: [u8; 2], /// IBAN length, intentionnaly short, the length is sufficient but if something changes it will raise error quickly pub iban_len: u8, /// position of bank identifier starting point @@ -55,22 +54,18 @@ impl fmt::Display for ValidationError { impl Error for ValidationError {} /// utility function to load the registry (as json) into a Hashmap -fn convert_to_hashmap( - json_str: &str, -) -> Result, serde_json::Error> { - +fn convert_to_hashmap(json_str: &str) -> Result, serde_json::Error> { let items: Vec = serde_json::from_str(json_str)?; - let map: HashMap<[u8;2], IbanFields> = items.into_iter() - .map(|item| (item.ctry_cd.clone(), item)) - .collect(); + let map: HashMap<[u8; 2], IbanFields> = + items.into_iter().map(|item| (item.ctry_cd, item)).collect(); Ok(map) } /// trigger the loading of the registry once need, and only once. /// panics if failing as there is no other way forward. -static IB_REG: LazyLock> = LazyLock::new(|| { +static IB_REG: LazyLock> = LazyLock::new(|| { convert_to_hashmap(include_str!("../data/iban_definitions.json")) .expect("Failed parsing JSON data into a HashMap") }); @@ -120,11 +115,11 @@ fn simple_contains_c(c: char) -> Result { } } -/// internal utility +/// internal utility /// division method for modulo 97 >> faster than regular modulo #[inline] fn division_mod97(x: u32) -> u32 { - let q = x / 97; // Quotient + let q = x / 97; // Quotient x - q * 97 // Remainder } @@ -136,8 +131,11 @@ pub const fn get_source_file() -> &'static str { /// Validate than an Iban is valid according to the registry information /// return true when Iban is fine, otherwise returns Error. pub fn validate_iban_str(input_iban: &str) -> Result { - let identified_country:[u8; 2] = match input_iban.get(..2) { - Some(value) => value.as_bytes().try_into().map_err(|_| ValidationError::InvalidCountry)?, + let identified_country: [u8; 2] = match input_iban.get(..2) { + Some(value) => value + .as_bytes() + .try_into() + .map_err(|_| ValidationError::InvalidCountry)?, None => return Err(ValidationError::MissingCountry), }; let pattern: &String = match &IB_REG.get(&identified_country) { @@ -150,9 +148,12 @@ pub fn validate_iban_str(input_iban: &str) -> Result { } // There is a potental panic but it should be a dead code, as we should never find a non 2-letter country code given we search for 2-leter country code and found something before - let pattern_start:[u8; 2]= pattern - .get(..2).unwrap() - .as_bytes().try_into().map_err(|_| ValidationError::InvalidCountry) + let pattern_start: [u8; 2] = pattern + .get(..2) + .unwrap() + .as_bytes() + .try_into() + .map_err(|_| ValidationError::InvalidCountry) .expect("Error the built-in pattern is not starting with at least two characters"); // first two letters do not match @@ -185,7 +186,8 @@ pub fn validate_iban_str(input_iban: &str) -> Result { true => 0, _ => return Err(ValidationError::StructureIncorrectForCountry), }, - _ => { // the 2-letter country code should match + _ => { + // the 2-letter country code should match if p == t { match simple_contains_a(t) { Ok(value) => value, @@ -196,12 +198,11 @@ pub fn validate_iban_str(input_iban: &str) -> Result { } } }; - acc *= if m97digit < 10 { 10 } else { 100 }; // Multiply by 10 (or 100 for two-digit numbers) - acc = division_mod97(acc + (m97digit as u32)); // and add new digit - + acc *= if m97digit < 10 { 10 } else { 100 }; // Multiply by 10 (or 100 for two-digit numbers) + acc = division_mod97(acc + (m97digit as u32)); // and add new digit } if acc == 1 { - Ok(true) + Ok(true) } else { Err(ValidationError::ModuloIncorrect) } @@ -228,8 +229,11 @@ impl<'a> Iban<'a> { Err(e) => return Err(e), }; - let identified_country:[u8; 2] = match s.get(..2) { - Some(value) => value.as_bytes().try_into().map_err(|_| ValidationError::InvalidCountry)?, + let identified_country: [u8; 2] = match s.get(..2) { + Some(value) => value + .as_bytes() + .try_into() + .map_err(|_| ValidationError::InvalidCountry)?, None => return Err(ValidationError::MissingCountry), }; @@ -240,8 +244,8 @@ impl<'a> Iban<'a> { let bank_id = if let Some(start) = iban_data.bank_id_pos_s { if let Some(end) = iban_data.bank_id_pos_e { - if start <= end && (4+start+(end-start)) <= s.len() { - Some(&s[start+3..4+start+(end-start)]) + if start <= end && (4 + start + (end - start)) <= s.len() { + Some(&s[start + 3..4 + start + (end - start)]) } else { None // Indices are invalid } @@ -254,8 +258,8 @@ impl<'a> Iban<'a> { let branch_id = if let Some(start) = iban_data.branch_id_pos_s { if let Some(end) = iban_data.branch_id_pos_e { - if start <= end && (4+start+(end-start)) <= s.len() { - Some(&s[start+3..4+start+(end-start)]) + if start <= end && (4 + start + (end - start)) <= s.len() { + Some(&s[start + 3..4 + start + (end - start)]) } else { None // Indices are invalid } @@ -465,7 +469,6 @@ mod tests { assert_eq!(the_test.get_iban(), "GE29NB0000000101904917"); assert_eq!(the_test.iban_bank_id.unwrap(), "NB"); assert_eq!(the_test.iban_branch_id, None); - } #[test] @@ -485,7 +488,6 @@ mod tests { #[test] fn test_filename() { - assert_eq!( get_source_file(), "iban_registry_v98.txt"); + assert_eq!(get_source_file(), "iban_registry_v98.txt"); } - }