1use std::fs::metadata;
2use std::io;
3use std::path::{Path, PathBuf};
4
5mod backglass;
6pub mod fixprint;
7mod frontend;
8pub mod patcher;
9
10pub mod config;
11
12pub mod indexer;
13
14pub mod cli;
15mod colorful_theme_patched;
16pub mod vpinball_config;
17
18pub fn strip_cr_lf(s: &str) -> String {
19 s.chars().filter(|c| !c.is_ascii_whitespace()).collect()
20}
21
22fn expand_path<S: AsRef<str>>(path: S) -> PathBuf {
23 shellexpand::tilde(path.as_ref()).to_string().into()
24}
25
26fn expand_path_exists<S: AsRef<str>>(path: S) -> io::Result<PathBuf> {
27 let expanded_path = shellexpand::tilde(path.as_ref());
29 path_exists(&PathBuf::from(expanded_path.to_string()))
30}
31
32fn path_exists(expanded_path: &Path) -> io::Result<PathBuf> {
33 match metadata(expanded_path) {
34 Ok(md) => {
35 if !md.is_file() && !md.is_dir() && md.is_symlink() {
36 Err(io::Error::new(
37 io::ErrorKind::InvalidInput,
38 format!("{} is not a file", expanded_path.display()),
39 ))
40 } else {
41 Ok(expanded_path.to_path_buf())
42 }
43 }
44 Err(msg) => {
45 let warning = format!(
46 "Failed to read metadata for {}: {}",
47 expanded_path.display(),
48 msg
49 );
50 Err(io::Error::new(io::ErrorKind::InvalidInput, warning))
51 }
52 }
53}
54
55fn os_independent_file_name(file_path: String) -> Option<String> {
56 if file_path.is_empty() {
59 return None;
60 }
61 file_path.rsplit(['/', '\\']).next().map(|f| f.to_string())
62}
63
64struct RemoveOnDrop {
66 path: PathBuf,
67}
68impl RemoveOnDrop {
69 fn new(path: PathBuf) -> Self {
70 RemoveOnDrop { path }
71 }
72
73 fn path(&self) -> &Path {
74 &self.path
75 }
76}
77
78impl Drop for RemoveOnDrop {
79 fn drop(&mut self) {
80 if self.path.exists() {
81 let _ = std::fs::remove_file(&self.path);
83 }
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_os_independent_file_name_windows() {
93 let file_path = "C:\\Users\\user\\Desktop\\file.txt";
94 let result = os_independent_file_name(file_path.to_string());
95 assert_eq!(result, Some("file.txt".to_string()));
96 }
97
98 #[test]
99 fn test_os_independent_file_unix() {
100 let file_path = "/users/joe/file.txt";
101 let result = os_independent_file_name(file_path.to_string());
102 assert_eq!(result, Some("file.txt".to_string()));
103 }
104
105 #[test]
106 fn test_os_independent_file_name_no_extension() {
107 let file_path = "C:\\Users\\user\\Desktop\\file";
108 let result = os_independent_file_name(file_path.to_string());
109 assert_eq!(result, Some("file".to_string()));
110 }
111
112 #[test]
113 fn test_os_independent_file_name_no_path() {
114 let file_path = "file.txt";
115 let result = os_independent_file_name(file_path.to_string());
116 assert_eq!(result, Some("file.txt".to_string()));
117 }
118
119 #[test]
120 fn test_os_independent_file_name_no_path_no_extension() {
121 let file_path = "file";
122 let result = os_independent_file_name(file_path.to_string());
123 assert_eq!(result, Some("file".to_string()));
124 }
125
126 #[test]
127 fn test_os_independent_file_name_empty() {
128 let file_path = "";
129 let result = os_independent_file_name(file_path.to_string());
130 assert_eq!(result, None);
131 }
132}