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 join(&self, path: &str) -> Self {
75 #[cfg(target_arch = "wasm32")]
76 {
77 TypedPath(self.0.join(path))
78 }
79 #[cfg(not(target_arch = "wasm32"))]
80 {
81 TypedPath(self.0.join(path))
82 }
83 }
84
85 pub fn join_typed(&self, path: &TypedPath) -> Self {
86 #[cfg(target_arch = "wasm32")]
87 {
88 TypedPath(self.0.join(path.0.to_path()))
89 }
90 #[cfg(not(target_arch = "wasm32"))]
91 {
92 TypedPath(self.0.join(&path.0))
93 }
94 }
95
96 pub fn parent(&self) -> Option<Self> {
97 #[cfg(target_arch = "wasm32")]
98 {
99 self.0.parent().map(|p| TypedPath(p.to_path_buf()))
100 }
101 #[cfg(not(target_arch = "wasm32"))]
102 {
103 self.0.parent().map(|p| TypedPath(p.to_path_buf()))
104 }
105 }
106
107 #[cfg(not(target_arch = "wasm32"))]
108 pub fn strip_prefix(&self, base: impl AsRef<std::path::Path>) -> Result<Self, std::path::StripPrefixError> {
109 self.0.strip_prefix(base).map(|p| TypedPath(p.to_path_buf()))
110 }
111
112 #[cfg(not(target_arch = "wasm32"))]
113 pub fn canonicalize(&self) -> Result<Self, std::io::Error> {
114 self.0.canonicalize().map(|p| TypedPath(p.to_path_buf()))
115 }
116
117 pub fn to_string_lossy(&self) -> String {
118 #[cfg(target_arch = "wasm32")]
119 {
120 self.0.to_path().to_string_lossy().to_string()
121 }
122 #[cfg(not(target_arch = "wasm32"))]
123 {
124 self.0.to_string_lossy().to_string()
125 }
126 }
127
128 pub fn display(&self) -> String {
129 #[cfg(target_arch = "wasm32")]
130 {
131 self.0.to_path().display().to_string()
132 }
133 #[cfg(not(target_arch = "wasm32"))]
134 {
135 self.0.display().to_string()
136 }
137 }
138
139 pub fn file_name(&self) -> Option<String> {
140 #[cfg(target_arch = "wasm32")]
141 {
142 self.0
143 .file_name()
144 .map(|s| std::str::from_utf8(s).unwrap_or(""))
145 .filter(|s| !s.is_empty())
146 .map(|s| s.to_string())
147 }
148 #[cfg(not(target_arch = "wasm32"))]
149 {
150 self.0.file_name().and_then(|s| s.to_str()).map(|s| s.to_string())
151 }
152 }
153}
154
155impl serde::Serialize for TypedPath {
156 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
157 where
158 S: serde::Serializer,
159 {
160 #[cfg(target_arch = "wasm32")]
161 {
162 self.0.to_str().serialize(serializer)
163 }
164 #[cfg(not(target_arch = "wasm32"))]
165 {
166 self.0.serialize(serializer)
167 }
168 }
169}
170
171impl<'de> serde::de::Deserialize<'de> for TypedPath {
172 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
173 where
174 D: serde::Deserializer<'de>,
175 {
176 #[cfg(target_arch = "wasm32")]
177 {
178 let path: String = serde::Deserialize::deserialize(deserializer)?;
179 Ok(TypedPath(typed_path::TypedPath::derive(&path).to_path_buf()))
180 }
181 #[cfg(not(target_arch = "wasm32"))]
182 {
183 let path: std::path::PathBuf = serde::Deserialize::deserialize(deserializer)?;
184 Ok(TypedPath(path))
185 }
186 }
187}
188
189impl ts_rs::TS for TypedPath {
190 type WithoutGenerics = Self;
191 type OptionInnerType = Self;
192
193 fn name() -> String {
194 "string".to_string()
195 }
196
197 fn decl() -> String {
198 std::path::PathBuf::decl()
199 }
200
201 fn decl_concrete() -> String {
202 std::path::PathBuf::decl_concrete()
203 }
204
205 fn inline() -> String {
206 std::path::PathBuf::inline()
207 }
208
209 fn inline_flattened() -> String {
210 std::path::PathBuf::inline_flattened()
211 }
212
213 fn output_path() -> Option<std::path::PathBuf> {
214 std::path::PathBuf::output_path()
215 }
216}
217
218impl schemars::JsonSchema for TypedPath {
219 fn schema_name() -> String {
220 "TypedPath".to_owned()
221 }
222
223 fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
224 r#gen.subschema_for::<std::path::PathBuf>()
226 }
227}
228
229#[cfg(not(target_arch = "wasm32"))]
235fn normalise_import<S: AsRef<str>>(raw: S) -> std::path::PathBuf {
236 let s = raw.as_ref();
237 if cfg!(unix) && s.contains('\\') {
240 std::path::PathBuf::from(s.replace('\\', "/"))
241 } else {
242 std::path::Path::new(s).to_path_buf()
243 }
244}