#![doc = include_str!("../README.md")]
#[macro_export]
macro_rules! path {
(@build_seg [$($result:expr),*] [$($current:tt)*] $lit:literal $($rest:tt)*) => {
path!(@build_seg [$($result,)* path!(@finish_seg [$($current)*]), $lit.to_string()] [] $($rest)*)
};
(@build_seg [$($result:expr),*] [$($current:tt)*] { $($expr:tt)+ } $($rest:tt)*) => {
path!(@build_seg [$($result,)* path!(@finish_seg [$($current)*]), ($($expr)+).to_string()] [] $($rest)*)
};
(@build_seg [$($result:expr),*] [$($current:tt)+] / $($rest:tt)*) => {
path!(@build_seg [$($result,)* path!(@finish_seg [$($current)+])] [] $($rest)*)
};
(@build_seg [$($result:expr),*] [] / $($rest:tt)*) => {
path!(@build_seg [$($result),*] [] $($rest)*)
};
(@build_seg [$($result:expr),*] [$($current:tt)+] , $($rest:tt)*) => {
path!(@build_seg [$($result,)* path!(@finish_seg [$($current)+])] [] $($rest)*)
};
(@build_seg [$($result:expr),*] [] , $($rest:tt)*) => {
path!(@build_seg [$($result),*] [] $($rest)*)
};
(@build_seg [$($result:expr),*] [$($current:tt)*] $next:tt $($rest:tt)*) => {
path!(@build_seg [$($result),*] [$($current)* $next] $($rest)*)
};
(@build_seg [$($result:expr),*] [$($current:tt)+]) => {
vec![$($result,)* path!(@finish_seg [$($current)+])]
};
(@build_seg [$($result:expr),*] []) => {
vec![$($result),*]
};
(@finish_seg []) => {
String::new()
};
(@finish_seg [$($tokens:tt)+]) => {
stringify!($($tokens)+).to_string()
};
($($tokens:tt)*) => {{
let segments: Vec<String> = path!(@build_seg [] [] $($tokens)*);
let mut path = std::path::PathBuf::new();
for seg in segments {
if !seg.is_empty() {
path.push(seg);
}
}
path
}};
}
#[cfg(target_os = "windows")]
#[macro_export]
macro_rules! path_const {
(@build [$($result:expr),*] [] $lit:literal / $($rest:tt)*) => {
path_const!(@build [$($result,)* $lit] [] $($rest)*)
};
(@build [$($result:expr),*] [] $lit:literal , $($rest:tt)*) => {
path_const!(@build [$($result,)* $lit] [] $($rest)*)
};
(@build [$($result:expr),*] [] $lit:literal) => {
path_const!(@concat $($result,)* $lit)
};
(@build [$($result:expr),*] [$($current:tt)+] / $($rest:tt)*) => {
path_const!(@build [$($result,)* path_const!(@finish [$($current)+])] [] $($rest)*)
};
(@build [$($result:expr),*] [] / $($rest:tt)*) => {
path_const!(@build [$($result),*] [] $($rest)*)
};
(@build [$($result:expr),*] [$($current:tt)+] , $($rest:tt)*) => {
path_const!(@build [$($result,)* path_const!(@finish [$($current)+])] [] $($rest)*)
};
(@build [$($result:expr),*] [] , $($rest:tt)*) => {
path_const!(@build [$($result),*] [] $($rest)*)
};
(@build [$($result:expr),*] [$($current:tt)*] $next:tt $($rest:tt)*) => {
path_const!(@build [$($result),*] [$($current)* $next] $($rest)*)
};
(@build [$($result:expr),*] [$($current:tt)+]) => {
path_const!(@concat $($result,)* path_const!(@finish [$($current)+]))
};
(@build [$($result:expr),*] []) => {
path_const!(@concat $($result),*)
};
(@finish []) => { "" };
(@finish [$($tokens:tt)+]) => { stringify!($($tokens)+) };
(@concat) => { "" };
(@concat $single:expr) => { $single };
(@concat $first:expr, $($rest:expr),+) => {
concat!($first, "\\", path_const!(@concat $($rest),+))
};
($($tokens:tt)*) => {
path_const!(@build [] [] $($tokens)*)
};
}
#[cfg(not(target_os = "windows"))]
#[macro_export]
macro_rules! path_const {
(@build [$($result:expr),*] [] $lit:literal / $($rest:tt)*) => {
path_const!(@build [$($result,)* $lit] [] $($rest)*)
};
(@build [$($result:expr),*] [] $lit:literal , $($rest:tt)*) => {
path_const!(@build [$($result,)* $lit] [] $($rest)*)
};
(@build [$($result:expr),*] [] $lit:literal) => {
path_const!(@concat $($result,)* $lit)
};
(@build [$($result:expr),*] [$($current:tt)+] / $($rest:tt)*) => {
path_const!(@build [$($result,)* path_const!(@finish [$($current)+])] [] $($rest)*)
};
(@build [$($result:expr),*] [] / $($rest:tt)*) => {
path_const!(@build [$($result),*] [] $($rest)*)
};
(@build [$($result:expr),*] [$($current:tt)+] , $($rest:tt)*) => {
path_const!(@build [$($result,)* path_const!(@finish [$($current)+])] [] $($rest)*)
};
(@build [$($result:expr),*] [] , $($rest:tt)*) => {
path_const!(@build [$($result),*] [] $($rest)*)
};
(@build [$($result:expr),*] [$($current:tt)*] $next:tt $($rest:tt)*) => {
path_const!(@build [$($result),*] [$($current)* $next] $($rest)*)
};
(@build [$($result:expr),*] [$($current:tt)+]) => {
path_const!(@concat $($result,)* path_const!(@finish [$($current)+]))
};
(@build [$($result:expr),*] []) => {
path_const!(@concat $($result),*)
};
(@finish []) => { "" };
(@finish [$($tokens:tt)+]) => { stringify!($($tokens)+) };
(@concat) => { "" };
(@concat $single:expr) => { $single };
(@concat $first:expr, $($rest:expr),+) => {
concat!($first, "/", path_const!(@concat $($rest),+))
};
($($tokens:tt)*) => {
path_const!(@build [] [] $($tokens)*)
};
}