libloading/
as_filename.rs1use crate::Error;
2use alloc::string::String;
3
4pub(crate) trait Sealed {
5 #[cfg(windows)]
6 #[doc(hidden)]
7 fn windows_filename<R>(
8 self,
9 function: impl FnOnce(*const u16) -> Result<R, crate::Error>,
10 ) -> Result<R, crate::Error>;
11
12 #[cfg(unix)]
13 #[doc(hidden)]
14 fn posix_filename<R>(
15 self,
16 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, crate::Error>,
17 ) -> Result<R, crate::Error>;
18}
19
20#[expect(private_bounds)]
25pub trait AsFilename: Sealed {}
26
27impl AsFilename for &str {}
28impl Sealed for &str {
29 #[cfg(windows)]
30 fn windows_filename<R>(
31 self,
32 function: impl FnOnce(*const u16) -> Result<R, Error>,
33 ) -> Result<R, Error> {
34 let utf16: alloc::vec::Vec<u16> = if crate::util::check_null_bytes(self.as_bytes())? {
35 self.encode_utf16().collect()
36 } else {
37 self.encode_utf16().chain(Some(0)).collect()
38 };
39 function(utf16.as_ptr())
40 }
41
42 #[cfg(unix)]
43 fn posix_filename<R>(
44 self,
45 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
46 ) -> Result<R, Error> {
47 if crate::util::check_null_bytes(self.as_bytes())? {
48 function(self.as_ptr().cast())
49 } else {
50 let buffer = crate::util::copy_and_push(self.as_bytes(), 0);
51 function(buffer.as_ptr().cast())
52 }
53 }
54}
55
56impl AsFilename for &String {}
57impl Sealed for &String {
58 #[cfg(windows)]
59 fn windows_filename<R>(
60 self,
61 function: impl FnOnce(*const u16) -> Result<R, Error>,
62 ) -> Result<R, Error> {
63 self.as_str().windows_filename(function)
64 }
65
66 #[cfg(unix)]
67 fn posix_filename<R>(
68 self,
69 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
70 ) -> Result<R, Error> {
71 self.as_str().posix_filename(function)
72 }
73}
74
75impl AsFilename for String {}
76impl Sealed for String {
77 #[cfg(windows)]
78 fn windows_filename<R>(
79 self,
80 function: impl FnOnce(*const u16) -> Result<R, Error>,
81 ) -> Result<R, Error> {
82 self.as_str().windows_filename(function)
83 }
84
85 #[cfg(unix)]
86 fn posix_filename<R>(
87 mut self,
88 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
89 ) -> Result<R, Error> {
90 if crate::util::check_null_bytes(self.as_bytes())? {
91 function(self.as_ptr().cast())
92 } else {
93 self.push('\0');
94 function(self.as_ptr().cast())
95 }
96 }
97}
98
99#[cfg(feature = "std")]
100#[cfg_attr(libloading_docs, doc(cfg(feature = "std")))]
101mod std {
102 use super::{Sealed, AsFilename};
103 use crate::Error;
104 use std::ffi::{OsStr, OsString};
105
106 impl AsFilename for &OsStr {}
107 impl Sealed for &OsStr {
108 #[cfg(windows)]
109 fn windows_filename<R>(
110 self,
111 function: impl FnOnce(*const u16) -> Result<R, Error>,
112 ) -> Result<R, Error> {
113 use std::os::windows::ffi::OsStrExt;
114 let bytes = self.as_encoded_bytes();
115 let utf16: alloc::vec::Vec<u16> = if crate::util::check_null_bytes(bytes)? {
116 self.encode_wide().collect()
117 } else {
118 self.encode_wide().chain(Some(0)).collect()
119 };
120 function(utf16.as_ptr())
121 }
122
123 #[cfg(unix)]
124 fn posix_filename<R>(
125 self,
126 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
127 ) -> Result<R, Error> {
128 let bytes = std::os::unix::ffi::OsStrExt::as_bytes(self);
129 if crate::util::check_null_bytes(bytes)? {
130 function(bytes.as_ptr().cast())
131 } else {
132 let buffer = crate::util::copy_and_push(bytes, 0);
133 function(buffer.as_ptr().cast())
134 }
135 }
136 }
137
138 impl AsFilename for &OsString {}
139 impl Sealed for &OsString {
140 #[cfg(windows)]
141 fn windows_filename<R>(
142 self,
143 function: impl FnOnce(*const u16) -> Result<R, Error>,
144 ) -> Result<R, Error> {
145 self.as_os_str().windows_filename(function)
146 }
147
148 #[cfg(unix)]
149 fn posix_filename<R>(
150 self,
151 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
152 ) -> Result<R, Error> {
153 self.as_os_str().posix_filename(function)
154 }
155 }
156
157 impl AsFilename for OsString {}
158 impl Sealed for OsString {
159 #[cfg(windows)]
160 fn windows_filename<R>(
161 self,
162 function: impl FnOnce(*const u16) -> Result<R, Error>,
163 ) -> Result<R, Error> {
164 self.as_os_str().windows_filename(function)
169 }
170
171 #[cfg(unix)]
172 fn posix_filename<R>(
173 self,
174 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
175 ) -> Result<R, Error> {
176 let mut bytes = std::os::unix::ffi::OsStringExt::into_vec(self);
177 if crate::util::check_null_bytes(&bytes)? {
178 function(bytes.as_ptr().cast())
179 } else {
180 bytes.push(0);
181 function(bytes.as_ptr().cast())
182 }
183 }
184 }
185
186 impl AsFilename for std::path::PathBuf {}
187 impl Sealed for std::path::PathBuf {
188 #[cfg(windows)]
189 fn windows_filename<R>(
190 self,
191 function: impl FnOnce(*const u16) -> Result<R, Error>,
192 ) -> Result<R, Error> {
193 self.into_os_string().windows_filename(function)
194 }
195
196 #[cfg(unix)]
197 fn posix_filename<R>(
198 self,
199 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
200 ) -> Result<R, Error> {
201 self.into_os_string().posix_filename(function)
202 }
203 }
204
205 impl AsFilename for &std::path::PathBuf {}
206 impl Sealed for &std::path::PathBuf {
207 #[cfg(windows)]
208 fn windows_filename<R>(
209 self,
210 function: impl FnOnce(*const u16) -> Result<R, Error>,
211 ) -> Result<R, Error> {
212 self.as_os_str().windows_filename(function)
213 }
214
215 #[cfg(unix)]
216 fn posix_filename<R>(
217 self,
218 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
219 ) -> Result<R, Error> {
220 self.as_os_str().posix_filename(function)
221 }
222 }
223
224 impl AsFilename for &std::path::Path {}
225 impl Sealed for &std::path::Path {
226 #[cfg(windows)]
227 fn windows_filename<R>(
228 self,
229 function: impl FnOnce(*const u16) -> Result<R, Error>,
230 ) -> Result<R, Error> {
231 self.as_os_str().windows_filename(function)
232 }
233
234 #[cfg(unix)]
235 fn posix_filename<R>(
236 self,
237 function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
238 ) -> Result<R, Error> {
239 self.as_os_str().posix_filename(function)
240 }
241 }
242}