fallow_types/
serde_path.rs1use std::path::{Path, PathBuf};
6
7use serde::Serializer;
8
9pub fn serialize<S: Serializer>(path: &Path, s: S) -> Result<S::Ok, S::Error> {
11 s.serialize_str(&path.to_string_lossy().replace('\\', "/"))
12}
13
14pub fn serialize_vec<S: Serializer>(paths: &[PathBuf], s: S) -> Result<S::Ok, S::Error> {
16 use serde::ser::SerializeSeq;
17 let mut seq = s.serialize_seq(Some(paths.len()))?;
18 for p in paths {
19 seq.serialize_element(&p.to_string_lossy().replace('\\', "/"))?;
20 }
21 seq.end()
22}
23
24#[cfg(test)]
25mod tests {
26 use std::path::Path;
27
28 fn normalize(path: &Path) -> String {
31 path.to_string_lossy().replace('\\', "/")
32 }
33
34 #[test]
35 fn unix_path_unchanged() {
36 assert_eq!(
37 normalize(Path::new("src/utils/index.ts")),
38 "src/utils/index.ts"
39 );
40 }
41
42 #[test]
43 fn empty_path() {
44 assert_eq!(normalize(Path::new("")), "");
45 }
46
47 #[test]
48 fn single_component_path() {
49 assert_eq!(normalize(Path::new("file.ts")), "file.ts");
50 }
51
52 #[test]
53 fn deep_nested_path() {
54 assert_eq!(normalize(Path::new("a/b/c/d/e.ts")), "a/b/c/d/e.ts");
55 }
56
57 #[test]
58 fn path_with_spaces() {
59 assert_eq!(
60 normalize(Path::new("my project/src/file.ts")),
61 "my project/src/file.ts"
62 );
63 }
64
65 #[test]
66 fn dot_relative_path() {
67 assert_eq!(normalize(Path::new("./src/file.ts")), "./src/file.ts");
68 }
69
70 #[test]
71 fn parent_relative_path() {
72 assert_eq!(normalize(Path::new("../other/file.ts")), "../other/file.ts");
73 }
74
75 #[test]
80 fn backslash_replacement_in_string() {
81 let windows_path = "src\\utils\\index.ts";
83 assert_eq!(windows_path.replace('\\', "/"), "src/utils/index.ts");
84 }
85
86 #[test]
87 fn mixed_separators_normalized() {
88 let mixed = "src/utils\\helpers\\index.ts";
89 assert_eq!(mixed.replace('\\', "/"), "src/utils/helpers/index.ts");
90 }
91
92 #[test]
93 fn backslash_only_path() {
94 let path = "src\\deep\\nested\\file.ts";
95 assert_eq!(path.replace('\\', "/"), "src/deep/nested/file.ts");
96 }
97}