Skip to main content

mangofetch_core/core/manager/
path_limits.rs

1#[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}