app_lib/
path_norm.rs

1//! Filesystem path strings as stored in SQLite: shorter keys on macOS.
2
3/// Strips the synthetic `/System/Volumes/Data` prefix when present so stored paths
4/// match user-visible paths and use fewer bytes in row data and FTS5 indexes.
5/// Matches traversal dedup in `audio_scanner`, `unified_walker`, etc.
6pub fn normalize_path_for_db(s: &str) -> String {
7    #[cfg(target_os = "macos")]
8    {
9        if s.starts_with("/System/Volumes/Data/") {
10            return s["/System/Volumes/Data".len()..].to_string();
11        }
12    }
13    s.to_string()
14}
15
16/// JSON array of path strings, each passed through [`normalize_path_for_db`].
17pub fn path_strings_json_normalized(paths: &[String]) -> String {
18    let v: Vec<String> = paths.iter().map(|p| normalize_path_for_db(p)).collect();
19    serde_json::to_string(&v).unwrap_or_default()
20}
21
22#[cfg(test)]
23mod tests {
24    use super::*;
25
26    #[test]
27    fn normalize_path_for_db_noop_without_prefix() {
28        assert_eq!(normalize_path_for_db("/Users/x/a.wav"), "/Users/x/a.wav");
29    }
30
31    #[test]
32    #[cfg(target_os = "macos")]
33    fn normalize_path_for_db_strips_data_volume() {
34        assert_eq!(
35            normalize_path_for_db("/System/Volumes/Data/Users/x/a.wav"),
36            "/Users/x/a.wav"
37        );
38    }
39
40    #[test]
41    #[cfg(not(target_os = "macos"))]
42    fn normalize_path_for_db_keeps_data_volume_on_non_macos() {
43        assert_eq!(
44            normalize_path_for_db("/System/Volumes/Data/Users/x/a.wav"),
45            "/System/Volumes/Data/Users/x/a.wav"
46        );
47    }
48}