Skip to content

Commit f750e57

Browse files
committed
fix(lex): Use new-ish OsStr API
Fixes #5280
1 parent 4b45d36 commit f750e57

File tree

1 file changed

+21
-52
lines changed

1 file changed

+21
-52
lines changed

clap_lex/src/ext.rs

+21-52
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ pub trait OsStrExt: private::Sealed {
183183

184184
impl OsStrExt for OsStr {
185185
fn try_str(&self) -> Result<&str, std::str::Utf8Error> {
186-
let bytes = to_bytes(self);
186+
let bytes = self.as_encoded_bytes();
187187
std::str::from_utf8(bytes)
188188
}
189189

@@ -192,22 +192,22 @@ impl OsStrExt for OsStr {
192192
}
193193

194194
fn find(&self, needle: &str) -> Option<usize> {
195-
let bytes = to_bytes(self);
195+
let bytes = self.as_encoded_bytes();
196196
(0..=self.len().checked_sub(needle.len())?)
197197
.find(|&x| bytes[x..].starts_with(needle.as_bytes()))
198198
}
199199

200200
fn strip_prefix(&self, prefix: &str) -> Option<&OsStr> {
201-
let bytes = to_bytes(self);
201+
let bytes = self.as_encoded_bytes();
202202
bytes.strip_prefix(prefix.as_bytes()).map(|s| {
203203
// SAFETY:
204-
// - This came from `to_bytes`
205-
// - Since `prefix` is `&str`, any split will be along UTF-8 boundarie
206-
unsafe { to_os_str_unchecked(s) }
204+
// - This came from `as_encoded_bytes`
205+
// - Since `prefix` is `&str`, any split will be along UTF-8 boundary
206+
unsafe { OsStr::from_encoded_bytes_unchecked(s) }
207207
})
208208
}
209209
fn starts_with(&self, prefix: &str) -> bool {
210-
let bytes = to_bytes(self);
210+
let bytes = self.as_encoded_bytes();
211211
bytes.starts_with(prefix.as_bytes())
212212
}
213213

@@ -222,13 +222,18 @@ impl OsStrExt for OsStr {
222222
fn split_once(&self, needle: &'_ str) -> Option<(&OsStr, &OsStr)> {
223223
let start = self.find(needle)?;
224224
let end = start + needle.len();
225-
let haystack = to_bytes(self);
225+
let haystack = self.as_encoded_bytes();
226226
let first = &haystack[0..start];
227227
let second = &haystack[end..];
228228
// SAFETY:
229-
// - This came from `to_bytes`
230-
// - Since `needle` is `&str`, any split will be along UTF-8 boundarie
231-
unsafe { Some((to_os_str_unchecked(first), to_os_str_unchecked(second))) }
229+
// - This came from `as_encoded_bytes`
230+
// - Since `needle` is `&str`, any split will be along UTF-8 boundary
231+
unsafe {
232+
Some((
233+
OsStr::from_encoded_bytes_unchecked(first),
234+
OsStr::from_encoded_bytes_unchecked(second),
235+
))
236+
}
232237
}
233238
}
234239

@@ -238,45 +243,6 @@ mod private {
238243
impl Sealed for std::ffi::OsStr {}
239244
}
240245

241-
/// Allow access to raw bytes
242-
///
243-
/// As the non-UTF8 encoding is not defined, the bytes only make sense when compared with
244-
/// 7-bit ASCII or `&str`
245-
///
246-
/// # Compatibility
247-
///
248-
/// There is no guarantee how non-UTF8 bytes will be encoded, even within versions of this crate
249-
/// (since its dependent on rustc)
250-
fn to_bytes(s: &OsStr) -> &[u8] {
251-
// SAFETY:
252-
// - Lifetimes are the same
253-
// - Types are compatible (`OsStr` is effectively a transparent wrapper for `[u8]`)
254-
// - The primary contract is that the encoding for invalid surrogate code points is not
255-
// guaranteed which isn't a problem here
256-
//
257-
// There is a proposal to support this natively (https://github.com/rust-lang/rust/pull/95290)
258-
// but its in limbo
259-
unsafe { std::mem::transmute(s) }
260-
}
261-
262-
/// Restore raw bytes as `OsStr`
263-
///
264-
/// # Safety
265-
///
266-
/// - `&[u8]` must either by a `&str` or originated with `to_bytes` within the same binary
267-
/// - Any splits of the original `&[u8]` must be done along UTF-8 boundaries
268-
unsafe fn to_os_str_unchecked(s: &[u8]) -> &OsStr {
269-
// SAFETY:
270-
// - Lifetimes are the same
271-
// - Types are compatible (`OsStr` is effectively a transparent wrapper for `[u8]`)
272-
// - The primary contract is that the encoding for invalid surrogate code points is not
273-
// guaranteed which isn't a problem here
274-
//
275-
// There is a proposal to support this natively (https://github.com/rust-lang/rust/pull/95290)
276-
// but its in limbo
277-
std::mem::transmute(s)
278-
}
279-
280246
pub struct Split<'s, 'n> {
281247
haystack: Option<&'s OsStr>,
282248
needle: &'n str,
@@ -309,7 +275,10 @@ impl<'s, 'n> Iterator for Split<'s, 'n> {
309275
///
310276
/// `index` must be at a valid UTF-8 boundary
311277
pub(crate) unsafe fn split_at(os: &OsStr, index: usize) -> (&OsStr, &OsStr) {
312-
let bytes = to_bytes(os);
278+
let bytes = os.as_encoded_bytes();
313279
let (first, second) = bytes.split_at(index);
314-
(to_os_str_unchecked(first), to_os_str_unchecked(second))
280+
(
281+
OsStr::from_encoded_bytes_unchecked(first),
282+
OsStr::from_encoded_bytes_unchecked(second),
283+
)
315284
}

0 commit comments

Comments
 (0)