gen_rs/
address.rs

1use regex::Regex;
2use std::cell::RefCell;
3
4
5/// Enum representing possible parse variants for an address that contain some number of `=>` separators.
6#[derive(Debug,PartialEq,Eq,Hash)]
7pub enum SplitAddr<'a> {
8    /// Resultant type from a parse of `(addr)`.
9    Term(&'a str),
10
11    /// Resultant type from a parse of `first => (addr)`.
12    Prefix(&'a str, &'a str)
13}
14use SplitAddr::{Prefix,Term};
15
16thread_local!(
17    /// Regex spec for address parsing.
18    static ADDR_RE: RefCell<Regex> = RefCell::new(Regex::new(r"^(.*?)=>(.*)$").ok().unwrap())
19);
20
21impl<'a> SplitAddr<'a> {
22    /// Parse a string address containing some number of `=>` separators into a `SplitAddr` variant.
23    pub fn from_addr(addr: &'a str) -> Self {
24        match ADDR_RE.with(|re| re.borrow().captures(&addr)) {
25            None => {
26                Term(addr.trim_start().trim_end())
27            },
28            Some(caps) => {
29                let first: &str = caps.get(1).unwrap().into();
30                let rest: &str = caps.get(2).unwrap().into();
31                Prefix(first.trim_start().trim_end(), rest)
32            }
33        }
34    }
35}
36
37/// Normalize whitespace between `=>` separators in an `addr` to contain one space to the left and right of each separator.
38pub fn normalize_addr<'a>(addr: &'a str) -> String {
39    match SplitAddr::from_addr(addr) {
40        Term(s) => {
41            s.to_string()
42        }
43        Prefix(first, rest) => {
44            format!("{} => {}", first, normalize_addr(rest))
45        }
46    }
47}
48
49#[test]
50fn test_split_addr() {
51    let key = SplitAddr::from_addr("test");
52    assert_eq!(key, Term("test"));
53
54    let key = SplitAddr::from_addr("(tuple, test)");
55    assert_eq!(key, Term("(tuple, test)"));
56
57    let key = SplitAddr::from_addr("1=>2");
58    assert_eq!(key, Prefix("1", "2"));
59
60    let hard_addr = " 1=> 21f23=>432 => 132  =>   (  y?A1 , grexxy )   ";
61    let mut key = SplitAddr::from_addr(hard_addr);
62    assert_eq!(key, Prefix("1", " 21f23=>432 => 132  =>   (  y?A1 , grexxy )   "));
63
64    while key != Term("(  y?A1 , grexxy )") {
65        match key {
66            Prefix(_, b) => { key = SplitAddr::from_addr(b); },
67            t => { panic!("expected term = Term(\"(  y?A1 , grexxy )\"), got {:?}", t) }
68        }
69    }
70
71    let equiv_addr = "1=>   21f23  => 432=>132 => (  y?A1 , grexxy ) ";
72    let normalized_addr = "1 => 21f23 => 432 => 132 => (  y?A1 , grexxy )";
73    assert_eq!(normalize_addr(hard_addr), normalized_addr);
74    assert_eq!(normalize_addr(equiv_addr), normalized_addr);
75}