mangofetch_core/core/manager/
path_limits.rs1#[cfg(target_os = "windows")]
2pub const MAX_PATH_LEN: usize = 259;
3#[cfg(not(target_os = "windows"))]
4pub const MAX_PATH_LEN: usize = 4095;
5
6pub const MIN_FILENAME_RESERVE: usize = 80;
7
8pub const SEPARATOR_RESERVE: usize = 1;
9
10#[derive(Debug, Clone, Copy)]
11pub struct PathLimitError {
12 pub limit: usize,
13 pub current: usize,
14 pub reserve: usize,
15}
16
17impl std::fmt::Display for PathLimitError {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 write!(
20 f,
21 "output path too long for OS limit (path uses {} of {} chars, need {} reserved for filename)",
22 self.current, self.limit, self.reserve
23 )
24 }
25}
26
27impl std::error::Error for PathLimitError {}
28
29pub fn validate_output_dir(output_dir: &str) -> Result<(), PathLimitError> {
30 let current = output_dir.chars().count() + SEPARATOR_RESERVE;
31 let reserve = MIN_FILENAME_RESERVE;
32 if current + reserve > MAX_PATH_LEN {
33 return Err(PathLimitError {
34 limit: MAX_PATH_LEN,
35 current,
36 reserve,
37 });
38 }
39 Ok(())
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn test_validate_output_dir_short_path() {
48 assert!(validate_output_dir("C:\\short\\path").is_ok());
49 }
50
51 #[test]
52 fn test_validate_output_dir_exact_limit() {
53 let exact_len = MAX_PATH_LEN - MIN_FILENAME_RESERVE - SEPARATOR_RESERVE;
54 let path = "a".repeat(exact_len);
55 assert!(validate_output_dir(&path).is_ok());
56 }
57
58 #[test]
59 fn test_validate_output_dir_over_limit() {
60 let over_len = MAX_PATH_LEN - MIN_FILENAME_RESERVE - SEPARATOR_RESERVE + 1;
61 let path = "a".repeat(over_len);
62 let result = validate_output_dir(&path);
63
64 assert!(result.is_err());
65 if let Err(e) = result {
66 assert_eq!(e.limit, MAX_PATH_LEN);
67 assert_eq!(e.current, over_len + SEPARATOR_RESERVE);
68 assert_eq!(e.reserve, MIN_FILENAME_RESERVE);
69 }
70 }
71}