fints_institute_db/
lib.rs1use serde::{Deserialize, Serialize};
17use std::str::FromStr;
18
19static BANKS: &str = include_str!(concat!(env!("OUT_DIR"), "/blz.properties"));
20
21#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)]
22pub struct Bank {
23 pub bank_code: String,
24 pub institute: String,
25 pub location: String,
26 pub bic: String,
27 pub checksum_method: String,
28 pub rdh_address: Option<String>,
29 pub pin_tan_address: Option<String>,
30 pub rdh_version: Option<String>,
31 pub pin_tan_version: Option<String>,
32}
33
34impl FromStr for Bank {
35 type Err = String;
36
37 fn from_str(s: &str) -> Result<Self, Self::Err> {
38 let first_part: Vec<&str> = s.split('=').collect();
41 let second_part: Vec<&str> = first_part[1].split('|').collect();
42
43 let bank = Bank {
44 bank_code: first_part[0].to_string(),
45 institute: second_part[0].to_string(),
46 location: second_part[1].to_string(),
47 bic: second_part[2].to_string(),
48 checksum_method: second_part[3].to_string(),
49 rdh_address: if second_part[4].is_empty() {
50 None
51 } else {
52 Some(second_part[4].to_string())
53 },
54 pin_tan_address: if second_part[5].is_empty() {
55 None
56 } else {
57 Some(second_part[5].to_string())
58 },
59 rdh_version: if second_part[6].is_empty() {
60 None
61 } else {
62 Some(second_part[6].to_string())
63 },
64 pin_tan_version: if second_part[7].is_empty() {
65 None
66 } else {
67 Some(second_part[7].to_string())
68 },
69 };
70 Ok(bank)
71 }
72}
73
74pub fn get_bank_by_bank_code(bank_code: &str) -> Option<Bank> {
87 for bank in BANKS.lines() {
88 let first_part: Vec<&str> = bank.split('=').collect();
89 let current_bank_code = first_part[0];
90 if current_bank_code == bank_code {
91 return Some(Bank::from_str(bank).expect(
92 "Invalid bank format found in source file.
93 This definitely shouldn't happen and is a serious issue with the bank info source file."
94 ));
95 }
96 }
97 None
98}
99
100pub fn get_bank_by_bic(bic: &str) -> Option<Bank> {
111 BANKS
112 .lines()
113 .map(Bank::from_str)
114 .filter_map(Result::ok)
115 .find(|b| b.bic == bic)
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121 use pretty_assertions::assert_eq;
122
123 fn assert_bank_matches(bank: &Bank) {
125 assert_eq!(bank.bank_code, "44761312");
126 assert_eq!(bank.institute, "Mendener Bank");
127 assert_eq!(bank.location, "Menden (Sauerland)");
128 assert_eq!(bank.bic, "GENODEM1MEN");
129 assert_eq!(bank.checksum_method, "34");
130 assert_eq!(bank.rdh_address, Some("hbci.gad.de".to_string()));
131 assert_eq!(
132 bank.pin_tan_address,
133 Some("https://fints1.atruvia.de/cgi-bin/hbciservlet".to_string())
134 );
135 assert_eq!(bank.rdh_version, Some("300".to_string()));
136 assert_eq!(bank.pin_tan_version, Some("300".to_string()));
137 }
138
139 #[test]
144 fn get_bank_by_bank_code_test() {
145 let bank_code = "44761312";
146 let bank = get_bank_by_bank_code(bank_code).unwrap();
147
148 assert_bank_matches(&bank);
149 }
150
151 #[test]
152 fn get_bank_by_bic_test() {
153 let bic = "GENODEM1MEN";
154 let bank = get_bank_by_bic(bic).unwrap();
155
156 assert_bank_matches(&bank);
157 }
158}
159
160#[cfg(doctest)]
161doc_comment::doctest!("../../README.md", readme);