1extern crate alloc;
4
5use alloc::borrow::Cow;
6#[cfg(feature = "std")]
7use std::{
8 ffi::{OsStr, OsString},
9 path::{Path, PathBuf},
10};
11
12#[macro_export]
21macro_rules! nonzero {
22 (0 $_:ident) => {
23 compile_error!("`0` passed to `nonzero!`")
24 };
25 ($n:literal) => {
26 core::num::NonZero::new($n).unwrap()
27 };
28}
29
30#[cfg(feature = "std")]
33pub(crate) unsafe fn bytes_as_path(bytes: &[u8]) -> &std::path::Path {
34 std::path::Path::new(std::ffi::OsStr::from_encoded_bytes_unchecked(bytes))
35}
36
37pub fn eq<T: PartialEq<Other>, Other>(x: T) -> impl Fn(&Other) -> bool {
39 move |y| &x == y
40}
41
42pub fn ne<T: PartialEq<Other>, Other>(x: T) -> impl Fn(&Other) -> bool {
44 move |y| &x != y
45}
46
47pub unsafe trait PathLike<'data>: Sized {
56 fn into_path_bytes(self) -> Cow<'data, [u8]>;
59
60 #[cfg(feature = "std")]
62 fn into_path(self) -> Cow<'data, Path> {
63 match self.into_path_bytes() {
64 Cow::Borrowed(x) => unsafe { bytes_as_path(x) }.into(),
65 Cow::Owned(x) => {
66 PathBuf::from(unsafe { OsString::from_encoded_bytes_unchecked(x) }).into()
67 }
68 }
69 }
70}
71
72macro_rules! impl_path_like {
73 (<$data:lifetime> for $t:ty: $self:ident => $res:expr) => {
74 unsafe impl<$data> PathLike<$data> for $t {
75 fn into_path_bytes(self) -> Cow<'data, [u8]> {let $self = self; $res.into()}
76 }
77 };
78
79 (owned $owned:ty: $self:ident => $res:expr) => {
80 unsafe impl PathLike<'static> for $owned {
81 fn into_path_bytes(self) -> Cow<'static, [u8]> {let $self = self; $res.into()}
82 }
83 };
84
85 (
86 $(for $owned:ty[$borrowed:ty]:
87 $self:ident => $res:expr;
88 box $bself:ident => $bres:expr;
89 ref $rself:ident => $rres:expr;
90 )+
91 ) => {
92 $(
93 impl_path_like!(owned $owned: $self => $res);
94 impl_path_like!(owned Box<$borrowed>: $bself => $bres);
95 impl_path_like!(<'data> for &'data $owned: $rself => $rres);
96 impl_path_like!(<'data> for &'data $borrowed: $rself => $rres);
97 impl_path_like!(<'data> for &'data Box<$borrowed>: $rself => $rres);
98 impl_path_like!(<'data> for &'data Cow<'data, $borrowed>: $rself => $rres);
99
100 unsafe impl<'data> PathLike<'data> for Cow<'data, $borrowed> {
101 fn into_path_bytes(self) -> Cow<'data, [u8]> {
102 match self {
103 Cow::Owned($self) => $res.into(),
104 Cow::Borrowed($rself) => $rres.into(),
105 }
106 }
107 }
108 )+
109 };
110}
111
112impl_path_like! {
113 for String[str]:
114 x => x.into_bytes();
115 box x => x.into_boxed_bytes().into_vec();
116 ref x => x.as_bytes();
117}
118
119#[cfg(feature = "std")]
120impl_path_like! {
121 for PathBuf[Path]:
122 x => x.into_os_string().into_encoded_bytes();
123 box x => x.into_path_buf().into_os_string().into_encoded_bytes();
124 ref x => x.as_os_str().as_encoded_bytes();
125 for OsString[OsStr]:
126 x => x.into_encoded_bytes();
127 box x => x.into_os_string().into_encoded_bytes();
128 ref x => x.as_encoded_bytes();
129}
130
131#[macro_export]
138macro_rules! any {
139 ($first:expr, $($rest:expr),* $(, $(else: $map_rest:expr)?)?) => {
140 $first $(.or($rest))* $($(.or_map_rest($map_rest))?)?
141 };
142}
143
144#[macro_export]
147macro_rules! match_out {
148 {
149 $($p:pat => $e:expr),+ $(,)?
150 } => {
151 |i, o| match o {
152 $($p => $e.parse(i)),+
153 }
154 };
155}