rs_path_filter_cel/
lib.rs

1use cel::Value;
2use cel::objects::{Key, Map};
3use std::collections::HashMap;
4use std::path::PathBuf;
5use std::sync::Arc;
6
7pub struct PathInfo {
8    full_path: PathBuf,
9}
10
11impl From<&str> for PathInfo {
12    fn from(s: &str) -> Self {
13        let path = PathBuf::from(s);
14        PathInfo { full_path: path }
15    }
16}
17
18impl From<PathInfo> for Value {
19    fn from(path_info: PathInfo) -> Self {
20        let mut map = Map {
21            map: Arc::new(HashMap::new()),
22        };
23
24        let path = &path_info.full_path;
25
26        if let Some(internal_map) = Arc::get_mut(&mut map.map) {
27            let ext = path
28                .extension()
29                .and_then(|s| s.to_str())
30                .unwrap_or("")
31                .to_string();
32            internal_map.insert(
33                Key::String(Arc::new("ext".to_string())),
34                Value::String(ext.into()),
35            );
36
37            if let Some(file_name) = path.file_name().and_then(|os_str| os_str.to_str()) {
38                internal_map.insert(
39                    Key::String(Arc::new("basename".to_string())),
40                    Value::String(file_name.to_string().into()),
41                );
42            }
43            if let Some(parent) = path.parent().and_then(|p| p.to_str()) {
44                internal_map.insert(
45                    Key::String(Arc::new("parent".to_string())),
46                    Value::String(parent.to_string().into()),
47                );
48            }
49            if let Some(file_stem) = path.file_stem().and_then(|os_str| os_str.to_str()) {
50                internal_map.insert(
51                    Key::String(Arc::new("file_stem".to_string())),
52                    Value::String(file_stem.to_string().into()),
53                );
54            }
55        }
56
57        Value::Map(map)
58    }
59}
60
61#[cfg(test)]
62#[allow(clippy::panic)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn test_path_info_from_str() {
68        let path_str = "dir1/dir2/file.txt";
69        let path_info = PathInfo::from(path_str);
70        assert_eq!(path_info.full_path, PathBuf::from(path_str));
71
72        let cel_value: Value = path_info.into();
73        if let Value::Map(map) = cel_value {
74            // Access internal map for assertions
75            let internal_map = map.map.as_ref();
76            assert_eq!(
77                internal_map.get(&Key::String(Arc::new("ext".to_string()))),
78                Some(&Value::String("txt".to_string().into()))
79            );
80            assert_eq!(
81                internal_map.get(&Key::String(Arc::new("basename".to_string()))),
82                Some(&Value::String("file.txt".to_string().into()))
83            );
84            assert_eq!(
85                internal_map.get(&Key::String(Arc::new("parent".to_string()))),
86                Some(&Value::String("dir1/dir2".to_string().into()))
87            );
88            assert_eq!(
89                internal_map.get(&Key::String(Arc::new("file_stem".to_string()))),
90                Some(&Value::String("file".to_string().into()))
91            );
92        } else {
93            panic!("Expected a CEL Map Value");
94        }
95    }
96
97    #[test]
98    fn test_path_info_root_path() {
99        let path_str = "/root/file.ext";
100        let path_info = PathInfo::from(path_str);
101        let cel_value: Value = path_info.into();
102        if let Value::Map(map) = cel_value {
103            let internal_map = map.map.as_ref();
104            assert_eq!(
105                internal_map.get(&Key::String(Arc::new("ext".to_string()))),
106                Some(&Value::String("ext".to_string().into()))
107            );
108            assert_eq!(
109                internal_map.get(&Key::String(Arc::new("basename".to_string()))),
110                Some(&Value::String("file.ext".to_string().into()))
111            );
112            assert_eq!(
113                internal_map.get(&Key::String(Arc::new("parent".to_string()))),
114                Some(&Value::String("/root".to_string().into()))
115            );
116            assert_eq!(
117                internal_map.get(&Key::String(Arc::new("file_stem".to_string()))),
118                Some(&Value::String("file".to_string().into()))
119            );
120        } else {
121            panic!("Expected a CEL Map Value");
122        }
123    }
124
125    #[test]
126    fn test_path_info_no_extension() {
127        let path_str = "dir/filename_no_ext";
128        let path_info = PathInfo::from(path_str);
129        let cel_value: Value = path_info.into();
130        if let Value::Map(map) = cel_value {
131            let internal_map = map.map.as_ref();
132            assert_eq!(
133                internal_map.get(&Key::String(Arc::new("ext".to_string()))),
134                Some(&Value::String("".to_string().into()))
135            );
136            assert_eq!(
137                internal_map.get(&Key::String(Arc::new("basename".to_string()))),
138                Some(&Value::String("filename_no_ext".to_string().into()))
139            );
140            assert_eq!(
141                internal_map.get(&Key::String(Arc::new("parent".to_string()))),
142                Some(&Value::String("dir".to_string().into()))
143            );
144            assert_eq!(
145                internal_map.get(&Key::String(Arc::new("file_stem".to_string()))),
146                Some(&Value::String("filename_no_ext".to_string().into()))
147            );
148        } else {
149            panic!("Expected a CEL Map Value");
150        }
151    }
152
153    #[test]
154    fn test_path_info_only_filename() {
155        let path_str = "file.csv";
156        let path_info = PathInfo::from(path_str);
157        let cel_value: Value = path_info.into();
158        if let Value::Map(map) = cel_value {
159            let internal_map = map.map.as_ref();
160            assert_eq!(
161                internal_map.get(&Key::String(Arc::new("ext".to_string()))),
162                Some(&Value::String("csv".to_string().into()))
163            );
164            assert_eq!(
165                internal_map.get(&Key::String(Arc::new("basename".to_string()))),
166                Some(&Value::String("file.csv".to_string().into()))
167            );
168            assert_eq!(
169                internal_map.get(&Key::String(Arc::new("parent".to_string()))),
170                Some(&Value::String("".to_string().into()))
171            );
172            assert_eq!(
173                internal_map.get(&Key::String(Arc::new("file_stem".to_string()))),
174                Some(&Value::String("file".to_string().into()))
175            );
176        } else {
177            panic!("Expected a CEL Map Value");
178        }
179    }
180
181    #[test]
182    fn test_path_info_dotfile() {
183        let path_str = ".config";
184        let path_info = PathInfo::from(path_str);
185        let cel_value: Value = path_info.into();
186        if let Value::Map(map) = cel_value {
187            let internal_map = map.map.as_ref();
188            assert_eq!(
189                internal_map.get(&Key::String(Arc::new("ext".to_string()))),
190                Some(&Value::String("".to_string().into()))
191            );
192            assert_eq!(
193                internal_map.get(&Key::String(Arc::new("basename".to_string()))),
194                Some(&Value::String(".config".to_string().into()))
195            );
196            assert_eq!(
197                internal_map.get(&Key::String(Arc::new("parent".to_string()))),
198                Some(&Value::String("".to_string().into()))
199            );
200            assert_eq!(
201                internal_map.get(&Key::String(Arc::new("file_stem".to_string()))),
202                Some(&Value::String(".config".to_string().into()))
203            );
204        } else {
205            panic!("Expected a CEL Map Value");
206        }
207    }
208
209    #[test]
210    fn test_path_info_multiple_dots() {
211        let path_str = "archive.tar.gz";
212        let path_info = PathInfo::from(path_str);
213        let cel_value: Value = path_info.into();
214        if let Value::Map(map) = cel_value {
215            let internal_map = map.map.as_ref();
216            assert_eq!(
217                internal_map.get(&Key::String(Arc::new("ext".to_string()))),
218                Some(&Value::String("gz".to_string().into()))
219            );
220            assert_eq!(
221                internal_map.get(&Key::String(Arc::new("basename".to_string()))),
222                Some(&Value::String("archive.tar.gz".to_string().into()))
223            );
224            assert_eq!(
225                internal_map.get(&Key::String(Arc::new("parent".to_string()))),
226                Some(&Value::String("".to_string().into()))
227            );
228            assert_eq!(
229                internal_map.get(&Key::String(Arc::new("file_stem".to_string()))),
230                Some(&Value::String("archive.tar".to_string().into()))
231            );
232        } else {
233            panic!("Expected a CEL Map Value");
234        }
235    }
236
237    #[test]
238    fn test_path_info_trailing_slash() {
239        let path_str = "my/dir/";
240        let path_info = PathInfo::from(path_str);
241        let cel_value: Value = path_info.into();
242        if let Value::Map(map) = cel_value {
243            let internal_map = map.map.as_ref();
244            assert_eq!(
245                internal_map.get(&Key::String(Arc::new("ext".to_string()))),
246                Some(&Value::String("".to_string().into()))
247            );
248            assert_eq!(
249                internal_map.get(&Key::String(Arc::new("basename".to_string()))),
250                Some(&Value::String("dir".to_string().into()))
251            );
252            assert_eq!(
253                internal_map.get(&Key::String(Arc::new("parent".to_string()))),
254                Some(&Value::String("my".to_string().into()))
255            );
256            assert_eq!(
257                internal_map.get(&Key::String(Arc::new("file_stem".to_string()))),
258                Some(&Value::String("dir".to_string().into()))
259            );
260        } else {
261            panic!("Expected a CEL Map Value");
262        }
263    }
264
265    #[test]
266    fn test_path_info_empty_path() {
267        let path_str = "";
268        let path_info = PathInfo::from(path_str);
269        let cel_value: Value = path_info.into();
270        if let Value::Map(map) = cel_value {
271            let internal_map = map.map.as_ref();
272            assert_eq!(
273                internal_map.get(&Key::String(Arc::new("ext".to_string()))),
274                Some(&Value::String("".to_string().into()))
275            );
276            assert!(!internal_map.contains_key(&Key::String(Arc::new("basename".to_string()))));
277            assert!(!internal_map.contains_key(&Key::String(Arc::new("parent".to_string()))));
278            assert!(!internal_map.contains_key(&Key::String(Arc::new("file_stem".to_string()))));
279        } else {
280            panic!("Expected a CEL Map Value");
281        }
282    }
283}