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> {
15 s.serialize_str(&path.to_string_lossy().replace('\\', "/"))
16}
17
18pub fn serialize_vec<S: Serializer>(paths: &[PathBuf], s: S) -> Result<S::Ok, S::Error> {
24 use serde::ser::SerializeSeq;
25 let mut seq = s.serialize_seq(Some(paths.len()))?;
26 for p in paths {
27 seq.serialize_element(&p.to_string_lossy().replace('\\', "/"))?;
28 }
29 seq.end()
30}
31
32#[cfg(test)]
33mod tests {
34 use std::path::Path;
35
36 fn normalize(path: &Path) -> String {
39 path.to_string_lossy().replace('\\', "/")
40 }
41
42 #[test]
43 fn unix_path_unchanged() {
44 assert_eq!(
45 normalize(Path::new("src/utils/index.ts")),
46 "src/utils/index.ts"
47 );
48 }
49
50 #[test]
51 fn empty_path() {
52 assert_eq!(normalize(Path::new("")), "");
53 }
54
55 #[test]
56 fn single_component_path() {
57 assert_eq!(normalize(Path::new("file.ts")), "file.ts");
58 }
59
60 #[test]
61 fn deep_nested_path() {
62 assert_eq!(normalize(Path::new("a/b/c/d/e.ts")), "a/b/c/d/e.ts");
63 }
64
65 #[test]
66 fn path_with_spaces() {
67 assert_eq!(
68 normalize(Path::new("my project/src/file.ts")),
69 "my project/src/file.ts"
70 );
71 }
72
73 #[test]
74 fn dot_relative_path() {
75 assert_eq!(normalize(Path::new("./src/file.ts")), "./src/file.ts");
76 }
77
78 #[test]
79 fn parent_relative_path() {
80 assert_eq!(normalize(Path::new("../other/file.ts")), "../other/file.ts");
81 }
82
83 #[test]
88 fn backslash_replacement_in_string() {
89 let windows_path = "src\\utils\\index.ts";
91 assert_eq!(windows_path.replace('\\', "/"), "src/utils/index.ts");
92 }
93
94 #[test]
95 fn mixed_separators_normalized() {
96 let mixed = "src/utils\\helpers\\index.ts";
97 assert_eq!(mixed.replace('\\', "/"), "src/utils/helpers/index.ts");
98 }
99
100 #[test]
101 fn backslash_only_path() {
102 let path = "src\\deep\\nested\\file.ts";
103 assert_eq!(path.replace('\\', "/"), "src/deep/nested/file.ts");
104 }
105}