pistonite_cu/str/
path_macro.rs1#[cfg(doc)]
91#[macro_export]
92macro_rules! path {
93 ($(&)? ident / $(ident_or_literal_or_expr) / * ) => {};
94 (literal / $(ident_or_literal_or_expr) / * ) => {};
95 ($(&)? ( path_expression ) / $(ident_or_literal_or_expr) / *) => {};
96}
97
98#[cfg(not(doc))]
99#[macro_export]
100macro_rules! path {
101 ($first:ident / $($rest_segs:tt)* ) => {{
102 let mut x = $first;
103 $crate::__path_internal!(x / $($rest_segs)*)
104 }};
105 ( & $first:ident / $($rest_segs:tt)* ) => {{
106 let mut x = std::path::PathBuf::from($first.to_owned());
107 $crate::__path_internal!(x / $($rest_segs)*)
108 }};
109 ($first:literal / $($rest_segs:tt)* ) => {{
110 let mut x = std::path::PathBuf::from($first);
111 $crate::__path_internal!(x / $($rest_segs)*)
112 }};
113 (( $first:expr ) / $($rest_segs:tt)* ) => {{
114 let mut x: ::std::path::PathBuf = { $first };
115 $crate::__path_internal!(x / $($rest_segs)*)
116 }};
117 ( & ( $first:expr ) / $($rest_segs:tt)* ) => {{
118 let x: &::std::path::Path = {$first}.as_ref();
119 let mut x = x.to_path_buf();
120 $crate::__path_internal!(x / $($rest_segs)*)
121 }};
122 ( $first:block / $($rest_segs:tt)* ) => {{
123 let mut x: ::std::path::PathBuf = $first;
124 $crate::__path_internal!(x / $($rest_segs)*)
125 }};
126 ( & $first:block / $($rest_segs:tt)* ) => {{
127 let x: &::std::path::Path = $first.as_ref();
128 let mut x = x.to_path_buf();
129 $crate::__path_internal!(x / $($rest_segs)*)
130 }};
131}
132
133#[macro_export]
134#[doc(hidden)]
135macro_rules! __path_internal {
136 ($first:ident / $second:literal) => {{
138 $first.push($second); $first
139 }};
140 ($first:ident / $second:ident) => {{
141 let x: &::std::path::Path = $second.as_ref();
142 $first.push(x); $first
143 }};
144 ($first:ident / $second:literal / $third:literal) => {{
145 $first.push($second); $first.push($third); $first
146 }};
147 ($first:ident / $second:literal / $third:ident) => {{
148 $first.push($second);
149 let x: &::std::path::Path = $third.as_ref();
150 $first.push(x); $first
151 }};
152 ($first:ident / $second:ident / $third:literal) => {{
153 let x: &::std::path::Path = $second.as_ref();
154 $first.push(x);
155 $first.push($third); $first
156 }};
157 ($first:ident / $second:ident / $third:ident) => {{
158 let x: &::std::path::Path = $second.as_ref();
159 $first.push(x);
160 let x: &::std::path::Path = $third.as_ref();
161 $first.push(x); $first
162 }};
163
164 ($first:ident / $second:literal / $third:literal / $($rest_segs:tt)* ) => {{
166 $first.push($second); $first.push($third);
167 $crate::__path_internal!($first / $($rest_segs)* )
168 }};
169 ($first:ident / $second:literal / $third:ident / $($rest_segs:tt)* ) => {{
170 $first.push($second);
171 let x: &::std::path::Path = $third.as_ref();
172 $first.push(x);
173 $crate::__path_internal!($first / $($rest_segs)* )
174 }};
175 ($first:ident / $second:literal / ( $third:expr ) / $($rest_segs:tt)* ) => {{
176 $first.push($second);
177 let x: &::std::path::Path = {$third}.as_ref();
178 $first.push(x);
179 $crate::__path_internal!($first / $($rest_segs)* )
180 }};
181 ($first:ident / $second:literal / $third:block / $($rest_segs:tt)* ) => {{
182 $first.push($second);
183 let x: &::std::path::Path = $third.as_ref();
184 $first.push(x);
185 $crate::__path_internal!($first / $($rest_segs)* )
186 }};
187 ($first:ident / $second:ident / $third:literal / $($rest_segs:tt)* ) => {{
188 let x: &::std::path::Path = $second.as_ref();
189 $first.push(x);
190 $first.push($third);
191 $crate::__path_internal!($first / $($rest_segs)* )
192 }};
193 ($first:ident / $second:ident / $third:ident / $($rest_segs:tt)* ) => {{
194 let x: &::std::path::Path = $second.as_ref();
195 $first.push(x);
196 let x: &::std::path::Path = $third.as_ref();
197 $first.push(x);
198 $crate::__path_internal!($first / $($rest_segs)* )
199 }};
200 ($first:ident / $second:ident / ( $third:expr ) / $($rest_segs:tt)* ) => {{
201 let x: &::std::path::Path = $second.as_ref();
202 $first.push(x);
203 let x: &::std::path::Path = {$third}.as_ref();
204 $first.push(x);
205 $crate::__path_internal!($first / $($rest_segs)* )
206 }};
207 ($first:ident / $second:ident / $third:block / $($rest_segs:tt)* ) => {{
208 let x: &::std::path::Path = $second.as_ref();
209 $first.push(x);
210 let x: &::std::path::Path = $third.as_ref();
211 $first.push(x);
212 $crate::__path_internal!($first / $($rest_segs)* )
213 }};
214 ($first:ident / ( $second:expr ) / $($rest_segs:tt)* ) => {{
216 let x: &::std::path::Path = {$second}.as_ref();
217 $first.push(x);
218 $crate::__path_internal!($first / $($rest_segs)* )
219 }};
220 ($first:ident / $second:block / $($rest_segs:tt)* ) => {{
221 let x: &::std::path::Path = $second.as_ref();
222 $first.push(x);
223 $crate::__path_internal!($first / $($rest_segs)* )
224 }};
225
226 ($first:ident / $second:literal / $third:expr) => {{
230 $first.push($second);
231 let x: &::std::path::Path = {$third}.as_ref();
232 $first.push(x); $first
233 }};
234 ($first:ident / $second:ident / $third:expr) => {{
235 let x: &::std::path::Path = $second.as_ref();
236 $first.push(x);
237 let x: &::std::path::Path = {$third}.as_ref();
238 $first.push(x); $first
239 }};
240 ($first:ident / $second:expr) => {{
241 let x: &::std::path::Path = {$second}.as_ref();
242 $first.push(x); $first
243 }};
244
245}
246
247#[cfg(test)]
248mod tests {
249 use std::path::{Path, PathBuf};
250
251 fn long_expected() -> PathBuf {
252 PathBuf::from("a")
253 .join("b")
254 .join("c")
255 .join("d")
256 .join("e")
257 .join("f")
258 .join("g")
259 .join("h")
260 .join("i")
261 .join("j")
262 }
263
264 #[test]
266 fn long_path_from_literal() {
267 let c = "c";
268 let e = String::from("e");
269 let h = "h";
270 let p = crate::path!("a" / "b" / (c) / "d" / (e.as_str()) / "f" / "g" / h / "i" / "j");
271 assert_eq!(p, long_expected());
272 let _ = (c, h); }
274
275 #[test]
277 fn long_path_from_owned() {
278 let base = PathBuf::from("a");
279 let b = "b";
280 let d = String::from("d");
281 let g = "g";
282 let p = crate::path!(base / (b) / "c" / (d.as_str()) / "e" / "f" / g / "h" / "i" / "j");
283 assert_eq!(p, long_expected());
284 let _ = (b, g);
285 }
286
287 #[test]
289 fn long_path_from_borrowed() {
290 let base = PathBuf::from("a");
291 let base_ref: &Path = base.as_path();
292 let c = String::from("c");
293 let f = "f";
294 let i = "i";
295 let p = crate::path!(&base_ref / "b" / (c.as_str()) / "d" / "e" / f / "g" / "h" / i / "j");
296 assert_eq!(p, long_expected());
297 let _ = (f, i);
298 }
299
300 #[test]
302 fn long_path_from_expr_owned() {
303 let d = "d";
304 let e = String::from("e");
305 let f = String::from("f");
306 let p = crate::path!(
307 (PathBuf::from("a")) / "b" / "c" / d / (&e) / (f.as_str()) / "g" / "h" / "i" / "j"
308 );
309 assert_eq!(p, long_expected());
310 let _ = d;
311 }
312
313 #[test]
315 fn long_path_from_expr_borrowed() {
316 let base = PathBuf::from("a");
317 let b = "b";
318 let e = String::from("e");
319 let j = "j";
320 let p = crate::path!(
321 &(base.as_path()) / b / "c" / "d" / (e.as_str()) / "f" / "g" / "h" / "i" / j
322 );
323 assert_eq!(p, long_expected());
324 let _ = (b, j);
325 }
326
327 #[test]
330 fn long_path_no_consecutive_same_type_even() {
331 let b = "b";
332 let c = String::from("c");
333 let e = "e";
334 let f = String::from("f");
335 let h = "h";
336 let i = String::from("i");
337 let p = crate::path!(
338 "a" / b / (c.as_str()) / "d" / e / (f.as_str()) / "g" / h / (i.as_str()) / "j"
339 );
340 assert_eq!(p, long_expected());
341 let _ = (b, e, h);
342 }
343
344 fn nine_expected() -> PathBuf {
345 PathBuf::from("a")
346 .join("b")
347 .join("c")
348 .join("d")
349 .join("e")
350 .join("f")
351 .join("g")
352 .join("h")
353 .join("i")
354 }
355
356 #[test]
359 fn long_path_no_consecutive_same_type_odd() {
360 let b = "b";
361 let c = String::from("c");
362 let e = "e";
363 let f = String::from("f");
364 let h = "h";
365 let i = String::from("i");
366 let p =
367 crate::path!("a" / b / (c.as_str()) / "d" / e / (f.as_str()) / "g" / h / i.as_str());
368 assert_eq!(p, nine_expected());
369 let _ = (b, e, h);
370 }
371}