kcl_lib/execution/
typed_path.rs1#[derive(Clone, Debug, PartialEq, Eq, Hash)]
5pub struct TypedPath(
6 #[cfg(target_arch = "wasm32")] pub typed_path::TypedPathBuf,
7 #[cfg(not(target_arch = "wasm32"))] pub std::path::PathBuf,
8);
9
10impl std::fmt::Display for TypedPath {
11 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12 #[cfg(target_arch = "wasm32")]
13 {
14 self.0.to_path().display().fmt(f)
15 }
16 #[cfg(not(target_arch = "wasm32"))]
17 {
18 self.0.display().fmt(f)
19 }
20 }
21}
22
23impl Default for TypedPath {
24 fn default() -> Self {
25 #[cfg(target_arch = "wasm32")]
26 {
27 TypedPath(typed_path::TypedPath::derive("").to_path_buf())
28 }
29 #[cfg(not(target_arch = "wasm32"))]
30 {
31 TypedPath(std::path::PathBuf::new())
32 }
33 }
34}
35
36impl From<&String> for TypedPath {
37 fn from(path: &String) -> Self {
38 TypedPath::new(path)
39 }
40}
41
42impl From<&str> for TypedPath {
43 fn from(path: &str) -> Self {
44 TypedPath::new(path)
45 }
46}
47
48impl TypedPath {
49 pub fn new(path: &str) -> Self {
50 #[cfg(target_arch = "wasm32")]
51 {
52 TypedPath(typed_path::TypedPath::derive(path).to_path_buf())
53 }
54 #[cfg(not(target_arch = "wasm32"))]
55 {
56 TypedPath(normalise_import(path))
57 }
58 }
59
60 pub fn extension(&self) -> Option<&str> {
61 #[cfg(target_arch = "wasm32")]
62 {
63 self.0
64 .extension()
65 .map(|s| std::str::from_utf8(s).map(|s| s.trim_start_matches('.')).unwrap_or(""))
66 .filter(|s| !s.is_empty())
67 }
68 #[cfg(not(target_arch = "wasm32"))]
69 {
70 self.0.extension().and_then(|s| s.to_str())
71 }
72 }
73
74 pub fn is_absolute(&self) -> bool {
75 self.0.is_absolute()
76 }
77
78 pub fn join(&self, path: &str) -> Self {
79 #[cfg(target_arch = "wasm32")]
80 {
81 TypedPath(self.0.join(path))
82 }
83 #[cfg(not(target_arch = "wasm32"))]
84 {
85 TypedPath(self.0.join(path))
86 }
87 }
88
89 pub fn join_typed(&self, path: &TypedPath) -> Self {
90 #[cfg(target_arch = "wasm32")]
91 {
92 TypedPath(self.0.join(path.0.to_path()))
93 }
94 #[cfg(not(target_arch = "wasm32"))]
95 {
96 TypedPath(self.0.join(&path.0))
97 }
98 }
99
100 pub fn parent(&self) -> Option<Self> {
101 #[cfg(target_arch = "wasm32")]
102 {
103 self.0.parent().map(|p| TypedPath(p.to_path_buf()))
104 }
105 #[cfg(not(target_arch = "wasm32"))]
106 {
107 self.0.parent().map(|p| TypedPath(p.to_path_buf()))
108 }
109 }
110
111 #[cfg(not(target_arch = "wasm32"))]
112 pub fn strip_prefix(&self, base: impl AsRef<std::path::Path>) -> Result<Self, std::path::StripPrefixError> {
113 self.0.strip_prefix(base).map(|p| TypedPath(p.to_path_buf()))
114 }
115
116 #[cfg(not(target_arch = "wasm32"))]
117 pub fn canonicalize(&self) -> Result<Self, std::io::Error> {
118 self.0.canonicalize().map(TypedPath)
119 }
120
121 pub fn to_string_lossy(&self) -> String {
122 #[cfg(target_arch = "wasm32")]
123 {
124 self.0.to_path().to_string_lossy().to_string()
125 }
126 #[cfg(not(target_arch = "wasm32"))]
127 {
128 self.0.to_string_lossy().to_string()
129 }
130 }
131
132 pub fn display(&self) -> String {
133 #[cfg(target_arch = "wasm32")]
134 {
135 self.0.to_path().display().to_string()
136 }
137 #[cfg(not(target_arch = "wasm32"))]
138 {
139 self.0.display().to_string()
140 }
141 }
142
143 pub fn file_name(&self) -> Option<String> {
144 #[cfg(target_arch = "wasm32")]
145 {
146 self.0
147 .file_name()
148 .map(|s| std::str::from_utf8(s).unwrap_or(""))
149 .filter(|s| !s.is_empty())
150 .map(|s| s.to_string())
151 }
152 #[cfg(not(target_arch = "wasm32"))]
153 {
154 self.0.file_name().and_then(|s| s.to_str()).map(|s| s.to_string())
155 }
156 }
157}
158
159impl serde::Serialize for TypedPath {
160 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
161 where
162 S: serde::Serializer,
163 {
164 #[cfg(target_arch = "wasm32")]
165 {
166 self.0.to_str().serialize(serializer)
167 }
168 #[cfg(not(target_arch = "wasm32"))]
169 {
170 self.0.serialize(serializer)
171 }
172 }
173}
174
175impl<'de> serde::de::Deserialize<'de> for TypedPath {
176 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
177 where
178 D: serde::Deserializer<'de>,
179 {
180 #[cfg(target_arch = "wasm32")]
181 {
182 let path: String = serde::Deserialize::deserialize(deserializer)?;
183 Ok(TypedPath(typed_path::TypedPath::derive(&path).to_path_buf()))
184 }
185 #[cfg(not(target_arch = "wasm32"))]
186 {
187 let path: std::path::PathBuf = serde::Deserialize::deserialize(deserializer)?;
188 Ok(TypedPath(path))
189 }
190 }
191}
192
193impl ts_rs::TS for TypedPath {
194 type WithoutGenerics = Self;
195 type OptionInnerType = Self;
196
197 fn name() -> String {
198 "string".to_string()
199 }
200
201 fn decl() -> String {
202 std::path::PathBuf::decl()
203 }
204
205 fn decl_concrete() -> String {
206 std::path::PathBuf::decl_concrete()
207 }
208
209 fn inline() -> String {
210 std::path::PathBuf::inline()
211 }
212
213 fn inline_flattened() -> String {
214 std::path::PathBuf::inline_flattened()
215 }
216
217 fn output_path() -> Option<std::path::PathBuf> {
218 std::path::PathBuf::output_path()
219 }
220}
221
222#[cfg(not(target_arch = "wasm32"))]
228fn normalise_import<S: AsRef<str>>(raw: S) -> std::path::PathBuf {
229 let s = raw.as_ref();
230 if cfg!(unix) && s.contains('\\') {
233 std::path::PathBuf::from(s.replace('\\', "/"))
234 } else {
235 std::path::Path::new(s).to_path_buf()
236 }
237}