Skip to content

Commit fb16fbb

Browse files
committed
switch to a different sealing style that retains documentation clarity
In particular with the supertrait based sealing users can't see which types implement the `AsFilename` and `AsSymbolName` traits. Which are pretty crucial things to know!
1 parent 873d9bf commit fb16fbb

File tree

5 files changed

+122
-111
lines changed

5 files changed

+122
-111
lines changed

src/as_filename.rs

Lines changed: 64 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,45 @@
1+
#![allow(private_interfaces)]
12
use crate::Error;
23
use alloc::string::String;
34

4-
mod private {
5-
6-
pub trait AsFilenameSeal {
7-
///
8-
/// This function is guaranteed to error or invoke the `FnOnce` parameter,
9-
/// and if called, return whatever the `FnOnce` returns.
10-
///
11-
/// The pointer parameter to the `FnOnce` is guaranteed to point to a valid "array" of
12-
/// undefined size which is terminated by a single '0' u16 and guaranteed to not contain
13-
/// interior '0' u16 elements.
14-
///
15-
/// The data the pointer points to is guaranteed to live until the `FnOnce` returns.
16-
///
17-
#[cfg(windows)]
18-
fn windows_filename<R>(
19-
self,
20-
function: impl FnOnce(*const u16) -> Result<R, crate::Error>,
21-
) -> Result<R, crate::Error>;
22-
23-
///
24-
/// This function is guaranteed to error or invoke the `FnOnce` parameter,
25-
/// and if called, return whatever the `FnOnce` returns.
26-
///
27-
/// The pointer parameter to the `FnOnce` is guaranteed to point to a valid 0 terminated
28-
/// c-string. The c-string is guaranteed to not contain interior '0' bytes.
29-
///
30-
/// The data the pointer points to is guaranteed to live until the `FnOnce` returns.
31-
///
32-
#[cfg(unix)]
33-
fn posix_filename<R>(
34-
self,
35-
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, crate::Error>,
36-
) -> Result<R, crate::Error>;
37-
}
38-
}
5+
pub(crate) struct SealedFilename;
396

40-
/// This trait is implemented on all types where libloading can derive a filename from.
41-
/// It is sealed and cannot be implemented by a user of libloading.
7+
/// This trait is implemented for types that can be used as a filename when loading new
8+
/// [`Library`](crate::Library) instances.
429
///
43-
pub trait AsFilename: private::AsFilenameSeal {}
44-
45-
impl<T> AsFilename for T where T: private::AsFilenameSeal {}
10+
/// It is currently sealed and cannot be implemented or its methods called by users of this crate.
11+
pub trait AsFilename {
12+
#[cfg(windows)]
13+
#[doc(hidden)]
14+
fn windows_filename<R>(
15+
self,
16+
sealed: SealedFilename,
17+
function: impl FnOnce(*const u16) -> Result<R, crate::Error>,
18+
) -> Result<R, crate::Error>;
19+
#[cfg(unix)]
20+
#[doc(hidden)]
21+
fn posix_filename<R>(
22+
self,
23+
sealed: SealedFilename,
24+
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, crate::Error>,
25+
) -> Result<R, crate::Error>;
26+
}
4627

47-
impl private::AsFilenameSeal for &str {
28+
impl AsFilename for &str {
4829
#[cfg(windows)]
4930
fn windows_filename<R>(
5031
self,
32+
_seal: SealedFilename,
5133
function: impl FnOnce(*const u16) -> Result<R, Error>,
5234
) -> Result<R, Error> {
53-
let mut utf16: alloc::vec::Vec<u16> = self.encode_utf16().chain(Some(0)).collect();
35+
let utf16: alloc::vec::Vec<u16> = self.encode_utf16().chain(Some(0)).collect();
5436
function(utf16.as_ptr())
5537
}
5638

5739
#[cfg(unix)]
5840
fn posix_filename<R>(
5941
self,
42+
_seal: SealedFilename,
6043
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
6144
) -> Result<R, Error> {
6245
if crate::util::check_null_bytes(self.as_bytes())? {
@@ -68,36 +51,40 @@ impl private::AsFilenameSeal for &str {
6851
}
6952
}
7053

71-
impl private::AsFilenameSeal for &String {
54+
impl AsFilename for &String {
7255
#[cfg(windows)]
7356
fn windows_filename<R>(
7457
self,
58+
seal: SealedFilename,
7559
function: impl FnOnce(*const u16) -> Result<R, Error>,
7660
) -> Result<R, Error> {
77-
self.as_str().windows_filename(function)
61+
self.as_str().windows_filename(seal, function)
7862
}
7963

8064
#[cfg(unix)]
8165
fn posix_filename<R>(
8266
self,
67+
seal: SealedFilename,
8368
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
8469
) -> Result<R, Error> {
85-
self.as_str().posix_filename(function)
70+
self.as_str().posix_filename(seal, function)
8671
}
8772
}
8873

89-
impl private::AsFilenameSeal for String {
74+
impl AsFilename for String {
9075
#[cfg(windows)]
9176
fn windows_filename<R>(
9277
self,
78+
seal: SealedFilename,
9379
function: impl FnOnce(*const u16) -> Result<R, Error>,
9480
) -> Result<R, Error> {
95-
self.as_str().windows_filename(function)
81+
self.as_str().windows_filename(seal, function)
9682
}
9783

9884
#[cfg(unix)]
9985
fn posix_filename<R>(
10086
mut self,
87+
_seal: SealedFilename,
10188
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
10289
) -> Result<R, Error> {
10390
if crate::util::check_null_bytes(self.as_bytes())? {
@@ -110,19 +97,20 @@ impl private::AsFilenameSeal for String {
11097
}
11198

11299
#[cfg(feature = "std")]
113-
#[cfg(any(windows, unix))]
100+
#[cfg_attr(libloading_docs, doc(cfg(feature = "std")))]
114101
mod std {
102+
use super::{AsFilename, SealedFilename};
115103
use crate::Error;
116-
use as_filename::private;
117104
use std::ffi::{OsStr, OsString};
118105

119-
impl private::AsFilenameSeal for &OsStr {
106+
impl AsFilename for &OsStr {
120107
#[cfg(windows)]
121108
fn windows_filename<R>(
122109
self,
110+
_seal: SealedFilename,
123111
function: impl FnOnce(*const u16) -> Result<R, Error>,
124112
) -> Result<R, Error> {
125-
let mut wide: alloc::vec::Vec<u16> = std::os::windows::ffi::OsStrExt::encode_wide(self)
113+
let wide: alloc::vec::Vec<u16> = std::os::windows::ffi::OsStrExt::encode_wide(self)
126114
.chain(Some(0))
127115
.collect();
128116
function(wide.as_ptr())
@@ -131,6 +119,7 @@ mod std {
131119
#[cfg(unix)]
132120
fn posix_filename<R>(
133121
self,
122+
_seal: SealedFilename,
134123
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
135124
) -> Result<R, Error> {
136125
let bytes = std::os::unix::ffi::OsStrExt::as_bytes(self);
@@ -143,40 +132,44 @@ mod std {
143132
}
144133
}
145134

146-
impl private::AsFilenameSeal for &OsString {
135+
impl AsFilename for &OsString {
147136
#[cfg(windows)]
148137
fn windows_filename<R>(
149138
self,
139+
seal: SealedFilename,
150140
function: impl FnOnce(*const u16) -> Result<R, Error>,
151141
) -> Result<R, Error> {
152-
self.as_os_str().windows_filename(function)
142+
self.as_os_str().windows_filename(seal, function)
153143
}
154144

155145
#[cfg(unix)]
156146
fn posix_filename<R>(
157147
self,
148+
seal: SealedFilename,
158149
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
159150
) -> Result<R, Error> {
160-
self.as_os_str().posix_filename(function)
151+
self.as_os_str().posix_filename(seal, function)
161152
}
162153
}
163154

164-
impl private::AsFilenameSeal for OsString {
155+
impl AsFilename for OsString {
165156
#[cfg(windows)]
166157
fn windows_filename<R>(
167158
self,
159+
seal: SealedFilename,
168160
function: impl FnOnce(*const u16) -> Result<R, Error>,
169161
) -> Result<R, Error> {
170162
// This is the best we can do.
171163
// There is no into_wide for windows.
172164
// The internal repr is wtf-8 and this is different
173165
// from LCPWSTR that we need for the ffi calls.
174-
self.as_os_str().windows_filename(function)
166+
self.as_os_str().windows_filename(seal, function)
175167
}
176168

177169
#[cfg(unix)]
178170
fn posix_filename<R>(
179171
self,
172+
_seal: SealedFilename,
180173
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
181174
) -> Result<R, Error> {
182175
let mut bytes = std::os::unix::ffi::OsStringExt::into_vec(self);
@@ -189,57 +182,63 @@ mod std {
189182
}
190183
}
191184

192-
impl private::AsFilenameSeal for std::path::PathBuf {
185+
impl AsFilename for std::path::PathBuf {
193186
#[cfg(windows)]
194187
fn windows_filename<R>(
195188
self,
189+
seal: SealedFilename,
196190
function: impl FnOnce(*const u16) -> Result<R, Error>,
197191
) -> Result<R, Error> {
198-
self.into_os_string().windows_filename(function)
192+
self.into_os_string().windows_filename(seal, function)
199193
}
200194

201195
#[cfg(unix)]
202196
fn posix_filename<R>(
203197
self,
198+
seal: SealedFilename,
204199
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
205200
) -> Result<R, Error> {
206-
self.into_os_string().posix_filename(function)
201+
self.into_os_string().posix_filename(seal, function)
207202
}
208203
}
209204

210-
impl private::AsFilenameSeal for &std::path::PathBuf {
205+
impl AsFilename for &std::path::PathBuf {
211206
#[cfg(windows)]
212207
fn windows_filename<R>(
213208
self,
209+
seal: SealedFilename,
214210
function: impl FnOnce(*const u16) -> Result<R, Error>,
215211
) -> Result<R, Error> {
216-
self.as_os_str().windows_filename(function)
212+
self.as_os_str().windows_filename(seal, function)
217213
}
218214

219215
#[cfg(unix)]
220216
fn posix_filename<R>(
221217
self,
218+
seal: SealedFilename,
222219
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
223220
) -> Result<R, Error> {
224-
self.as_os_str().posix_filename(function)
221+
self.as_os_str().posix_filename(seal, function)
225222
}
226223
}
227224

228-
impl private::AsFilenameSeal for &std::path::Path {
225+
impl AsFilename for &std::path::Path {
229226
#[cfg(windows)]
230227
fn windows_filename<R>(
231228
self,
229+
seal: SealedFilename,
232230
function: impl FnOnce(*const u16) -> Result<R, Error>,
233231
) -> Result<R, Error> {
234-
self.as_os_str().windows_filename(function)
232+
self.as_os_str().windows_filename(seal, function)
235233
}
236234

237235
#[cfg(unix)]
238236
fn posix_filename<R>(
239237
self,
238+
seal: SealedFilename,
240239
function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
241240
) -> Result<R, Error> {
242-
self.as_os_str().posix_filename(function)
241+
self.as_os_str().posix_filename(seal, function)
243242
}
244243
}
245244
}

0 commit comments

Comments
 (0)