iban_parser/
lib.rs

1#![doc=include_str!("../README.md")]
2
3mod core;
4mod country;
5
6#[derive(Debug, PartialEq)]
7pub struct Iban {
8    /// IBAN as provided
9    pub raw_iban: String,
10    /// Sanitised IBAN, without whitespaces and all uppercased. Will be filled even if the IBAN is invalid.
11    pub machine_iban: String,
12    // TODO prettify machine IBAN to a string like GB82 WEST 1234 5698 7654 32.
13    // pretty_iban: String,
14    /// The country code of the IBAN, such as GB or NL.
15    pub country_code: String,
16    /// Check digits as provided, which are the 2 digits that follow the country code, such as 82.
17    pub check_digits: String,
18    /// Same as check_digits, but as an int.
19    pub check_digits_int: i8,
20    /// BBAN is a substring of the IBAN, being the country-specific alphanumeric characters that follow after the country code and check digits.
21    pub bban: String,
22    /// Whether this is a valid iban or not.
23    pub is_valid: bool,
24}
25
26/// Parses a string into an `IBAN` struct, containing a sanitised IBAN, is_valid, country code, BBAN and check digits
27pub fn parse_iban(iban_string: &str) -> Iban {
28    let sanitised = core::sanitise_iban(iban_string);
29    let mut chars = sanitised.chars();
30    let country_code: String = chars.by_ref().take(2).collect();
31    let check_digits: String = chars.by_ref().take(2).collect();
32    let bban: String = chars.by_ref().take(40).collect();
33
34    let is_valid = core::is_valid_checksum(&country_code, &check_digits, &bban) && country::is_country_code_valid(&country_code) && core::validate_length(&sanitised);
35 
36    Iban {
37        raw_iban: iban_string.to_string(),
38        bban,
39        machine_iban: sanitised,
40        is_valid,
41        country_code,
42        check_digits_int: check_digits.clone().parse().unwrap(),
43        check_digits
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    #[test]
52    fn parser_works() {
53        let input = "GB82 WEST 1234 5698 7654 32";
54
55        let result = parse_iban(input);
56
57        assert_eq!(result, Iban {
58            country_code: String::from("GB"),
59            check_digits: String::from("82"),
60            check_digits_int: 82,
61            bban: String::from("WEST12345698765432"),
62            is_valid: true,
63            raw_iban: input.to_string(),
64            machine_iban: String::from("GB82WEST12345698765432")
65        })
66    }
67
68    #[test]
69    fn country_code_validation() {
70        let good = "GB82 WEST 1234 5698 7654 32";
71        let bad = "BB82 WEST 1234 5698 7654 32";
72
73        let good_result = parse_iban(good);
74        let bad_result = parse_iban(bad);
75
76        assert!(good_result.is_valid);
77        assert!(!bad_result.is_valid);
78    }
79}
80
81#[cfg(test)]
82mod integration_test;