iban-tools

Tools / code generators for IBAN validation
Log | Files | Refs

commit 1a693daa459cf24202142db2763f08d97ddc6e70
parent c303d3aadedf9e3e4333405c459bbe0f17843262
Author: Antoine A <>
Date:   Tue, 18 Feb 2025 15:35:01 +0100

Improve rs codegen

Diffstat:
A.gitignore | 2++
Mcodegen_rs.py | 68+++++++++++++++++++++++---------------------------------------------
2 files changed, 25 insertions(+), 45 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +registry.* +\ No newline at end of file diff --git a/codegen_rs.py b/codegen_rs.py @@ -68,39 +68,34 @@ pub enum PatternErr { } """ -def gen_range(name): +def gen_match(name, return_type, match): global rust - rust += f"""pub const fn {name}_id(self) -> core::ops::Range<usize> {{ - match self {{ - """ + rust += f"pub const fn {name}(self) -> {return_type} {{\nmatch self {{\n" for r in registry: + rust += f"{r['code']} => {match(r)},\n" + rust += "}\n}\n\n" + + +def gen_range(name): + def fmt_range(r): (start, end) = r[name + "_range"] or [0, 0] - rust += f" {r['code']} => {start}..{end},\n" - rust += """ } - } - """ + return f"{start}..{end}" + gen_match(f"{name}_id", "core::ops::Range<usize>", fmt_range) def gen_pattern(name): - global rust - rust += f"""pub const fn {name}_pattern(self) -> Pattern {{ - match self {{ - """ - for r in registry: + def fmt_pattern(r): pattern = r[name + "_rules"] or [] - rust += f"{r['code']} => &[" + fmt = "&[" for repetition, char in pattern: - rust += f"({repetition}, {char.upper()})," - rust += "],\n" - rust += """ } - } - """ + fmt += f"({repetition}, {char.upper()})," + return fmt + "]" + gen_match(f"{name}_pattern", "Pattern", fmt_pattern) def gen_check(name): global rust - rust += "\n" - rust += f"""pub(crate) fn {name}_check(self, iban_ascii: &[u8]) -> Result<(), PatternErr> {{ + rust += f"""pub fn {name}_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())); match self {{ @@ -124,10 +119,7 @@ def gen_check(name): return Err(PatternErr::Malformed) }""" rust += "\n}\n" - rust += """ } - Ok(()) - } - """ + rust += "}\nOk(())\n}\n" rust += "#[derive(Debug, Clone, Copy, PartialEq, Eq)]\n" rust += "pub enum Country {\n" @@ -142,24 +134,9 @@ for r in registry: rust += " _ => None,\n" rust += " }\n" rust += "}\n\n" -rust += "pub fn as_str(self) -> &'static str {\n" -rust += " match self {\n" -for r in registry: - rust += f'{r["code"]} => "{r["code"]}",\n' -rust += " }\n" -rust += "}\n\n" -rust += "pub fn as_bytes(self) -> [u8; 2] {\n" -rust += " match self {\n" -for r in registry: - rust += f"{r['code']} => [b'{r['code'][0]}', b'{r['code'][1]}'],\n" -rust += " }\n" -rust += "}\n\n" -rust += "pub const fn iban_len(self) -> usize {\n" -rust += " match self {\n" -for r in registry: - rust += f"{r['code']} => {r['iban_len']},\n" -rust += " }\n" -rust += "}\n\n" +gen_match("as_str", "&'static str", lambda r: f'"{r["code"]}"') +gen_match("as_bytes", "[u8; 2]", lambda r: f"[b'{r['code'][0]}', b'{r['code'][1]}']") +gen_match("iban_len", "usize", lambda r: f"{r['iban_len']}") rust += "pub const fn bban_len(self) -> usize {\n" rust += " self.iban_len() - 4\n" rust += "}\n\n" @@ -203,10 +180,11 @@ for r in registry: rust += f'("{r["iban_example"]}", ' bban = r["bban_example"] if bban is None: - rust += "None),\n" + rust += "None" else: bban = "".join(filter(str.isalnum, bban)) - rust += f'Some("{bban}")),\n' + rust += f'Some("{bban}")' + rust += "),\n" rust += "]\n;" with open("registry.rs", "w") as rs_file: