1use regex::Regex;
2use std::cell::RefCell;
3
4
5#[derive(Debug,PartialEq,Eq,Hash)]
7pub enum SplitAddr<'a> {
8 Term(&'a str),
10
11 Prefix(&'a str, &'a str)
13}
14use SplitAddr::{Prefix,Term};
15
16thread_local!(
17 static ADDR_RE: RefCell<Regex> = RefCell::new(Regex::new(r"^(.*?)=>(.*)$").ok().unwrap())
19);
20
21impl<'a> SplitAddr<'a> {
22 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
37pub 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}