rust_sql_organizer/sorter/
mod.rs

1use phf::{phf_map, Map};
2use regex::Regex;
3use std::{cmp::Ordering, path::PathBuf};
4
5use lazy_static::lazy_static;
6
7#[derive(Debug, Eq, PartialEq, Clone)]
8pub enum Key {
9    Num(i32),
10    Text(String),
11}
12
13impl Ord for Key {
14    fn cmp(&self, other: &Self) -> Ordering {
15        match (self, other) {
16            (Key::Num(a), Key::Num(b)) => a.cmp(b),
17            (Key::Text(a), Key::Text(b)) => a.cmp(b),
18            (Key::Num(_), Key::Text(_)) => Ordering::Less,
19            (Key::Text(_), Key::Num(_)) => Ordering::Greater,
20        }
21    }
22}
23
24impl PartialOrd for Key {
25    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
26        Some(self.cmp(other))
27    }
28}
29
30pub type OrdFn = fn(&PathBuf) -> Key;
31
32lazy_static! {
33    static ref NUMBER_RE: Regex = Regex::new("[0-9]+").unwrap();
34    pub static ref SORTING_STRATEGIES: Map<&'static str, OrdFn> = phf_map! {
35        "first_number" => |path| {
36            let file_name = path.file_name().unwrap().to_str().unwrap_or("");
37            let num: i32 = match NUMBER_RE.find(file_name) {
38                Some(m) => m.as_str().parse().unwrap(),
39                None => 0,
40            };
41            Key::Num(num)
42        },
43        "last_number" => |path| {
44            let file_name = path.file_name().unwrap().to_str().unwrap_or("");
45            let num: i32 = match NUMBER_RE.find_iter(file_name).last() {
46                Some(m) => m.as_str().parse().unwrap(),
47                None => 0,
48            };
49            Key::Num(num)
50        },
51        "folder" => |path| {
52            let last_folder_name = match path.parent() {
53                Some(p) => match p.file_name() {
54                    Some(name) => name.to_str().unwrap(),
55                    None => return Key::Num(0),
56                },
57                None => return Key::Num(0),
58            };
59            Key::Text(last_folder_name.to_string())
60        }
61    };
62}
63
64#[cfg(test)]
65mod test_sorters {
66    use std::path::Path;
67
68    use super::{Key, SORTING_STRATEGIES};
69
70    #[test]
71    fn test_first_number() {
72        let first_number_strat = SORTING_STRATEGIES.get("first_number").unwrap();
73        assert_eq!(
74            first_number_strat(&Path::new("folder/100_deploy_20.sql").to_path_buf()),
75            Key::Num(100)
76        );
77    }
78
79    #[test]
80    fn test_last_number() {
81        let strat = SORTING_STRATEGIES.get("last_number").unwrap();
82        assert_eq!(
83            strat(&Path::new("folder/100_deploy_20.sql").to_path_buf()),
84            Key::Num(20)
85        );
86    }
87
88    #[test]
89    fn test_folder() {
90        let strat = SORTING_STRATEGIES.get("folder").unwrap();
91        assert_eq!(
92            strat(&Path::new("folder/100_deploy_20.sql").to_path_buf()),
93            Key::Text("folder".to_string())
94        )
95    }
96
97    #[test]
98    fn test_folder_no_folder() {
99        let strat = SORTING_STRATEGIES.get("folder").unwrap();
100        assert_eq!(
101            strat(&Path::new("/100_deploy_20.sql").to_path_buf()),
102            Key::Num(0)
103        )
104    }
105}