Rollup merge of #69937 - TyPR124:osstr_ascii, r=dtolnay
ASCII methods on OsStr Would close #69566 I don't know enough about encodings to know if this is a valid change, however the comment on the issue suggests it could be. This does two things: 1. Makes ASCII methods available on OsStr 2. Makes it possible to obtain a `&mut OsStr`. This is necessary to actually use `OsStr::make_ascii_*case` methods since they modify the underlying value. As far as I can tell, the only way to modify a `&mut OsStr` is via the methods I just added. My original hope was to have these methods on `OsStrExt` for Windows, since the standard library already assumes `make_ascii_uppercase` is valid in Windows (see the change I made to windows/process.rs). If it is found these are not valid changes on non-Windows platforms, I can move the methods to the ext trait instead.
This commit is contained in:
commit
d584f5a386
5 changed files with 235 additions and 11 deletions
|
@ -698,6 +698,147 @@ impl OsStr {
|
|||
fn bytes(&self) -> &[u8] {
|
||||
unsafe { &*(&self.inner as *const _ as *const [u8]) }
|
||||
}
|
||||
|
||||
/// Converts this string to its ASCII lower case equivalent in-place.
|
||||
///
|
||||
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To return a new lowercased value without modifying the existing one, use
|
||||
/// [`to_ascii_lowercase`].
|
||||
///
|
||||
/// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(osstring_ascii)]
|
||||
/// use std::ffi::OsString;
|
||||
///
|
||||
/// let mut s = OsString::from("GRÜßE, JÜRGEN ❤");
|
||||
///
|
||||
/// s.make_ascii_lowercase();
|
||||
///
|
||||
/// assert_eq!("grÜße, jÜrgen ❤", s);
|
||||
/// ```
|
||||
#[unstable(feature = "osstring_ascii", issue = "70516")]
|
||||
pub fn make_ascii_lowercase(&mut self) {
|
||||
self.inner.make_ascii_lowercase()
|
||||
}
|
||||
|
||||
/// Converts this string to its ASCII upper case equivalent in-place.
|
||||
///
|
||||
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To return a new uppercased value without modifying the existing one, use
|
||||
/// [`to_ascii_uppercase`].
|
||||
///
|
||||
/// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(osstring_ascii)]
|
||||
/// use std::ffi::OsString;
|
||||
///
|
||||
/// let mut s = OsString::from("Grüße, Jürgen ❤");
|
||||
///
|
||||
/// s.make_ascii_uppercase();
|
||||
///
|
||||
/// assert_eq!("GRüßE, JüRGEN ❤", s);
|
||||
/// ```
|
||||
#[unstable(feature = "osstring_ascii", issue = "70516")]
|
||||
pub fn make_ascii_uppercase(&mut self) {
|
||||
self.inner.make_ascii_uppercase()
|
||||
}
|
||||
|
||||
/// Returns a copy of this string where each character is mapped to its
|
||||
/// ASCII lower case equivalent.
|
||||
///
|
||||
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To lowercase the value in-place, use [`make_ascii_lowercase`].
|
||||
///
|
||||
/// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(osstring_ascii)]
|
||||
/// use std::ffi::OsString;
|
||||
/// let s = OsString::from("Grüße, Jürgen ❤");
|
||||
///
|
||||
/// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
|
||||
/// ```
|
||||
#[unstable(feature = "osstring_ascii", issue = "70516")]
|
||||
pub fn to_ascii_lowercase(&self) -> OsString {
|
||||
OsString::from_inner(self.inner.to_ascii_lowercase())
|
||||
}
|
||||
|
||||
/// Returns a copy of this string where each character is mapped to its
|
||||
/// ASCII upper case equivalent.
|
||||
///
|
||||
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To uppercase the value in-place, use [`make_ascii_uppercase`].
|
||||
///
|
||||
/// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(osstring_ascii)]
|
||||
/// use std::ffi::OsString;
|
||||
/// let s = OsString::from("Grüße, Jürgen ❤");
|
||||
///
|
||||
/// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
|
||||
/// ```
|
||||
#[unstable(feature = "osstring_ascii", issue = "70516")]
|
||||
pub fn to_ascii_uppercase(&self) -> OsString {
|
||||
OsString::from_inner(self.inner.to_ascii_uppercase())
|
||||
}
|
||||
|
||||
/// Checks if all characters in this string are within the ASCII range.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(osstring_ascii)]
|
||||
/// use std::ffi::OsString;
|
||||
///
|
||||
/// let ascii = OsString::from("hello!\n");
|
||||
/// let non_ascii = OsString::from("Grüße, Jürgen ❤");
|
||||
///
|
||||
/// assert!(ascii.is_ascii());
|
||||
/// assert!(!non_ascii.is_ascii());
|
||||
/// ```
|
||||
#[unstable(feature = "osstring_ascii", issue = "70516")]
|
||||
pub fn is_ascii(&self) -> bool {
|
||||
self.inner.is_ascii()
|
||||
}
|
||||
|
||||
/// Checks that two strings are an ASCII case-insensitive match.
|
||||
///
|
||||
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
|
||||
/// but without allocating and copying temporaries.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(osstring_ascii)]
|
||||
/// use std::ffi::OsString;
|
||||
///
|
||||
/// assert!(OsString::from("Ferris").eq_ignore_ascii_case("FERRIS"));
|
||||
/// assert!(OsString::from("Ferrös").eq_ignore_ascii_case("FERRöS"));
|
||||
/// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS"));
|
||||
/// ```
|
||||
#[unstable(feature = "osstring_ascii", issue = "70516")]
|
||||
pub fn eq_ignore_ascii_case<S: ?Sized + AsRef<OsStr>>(&self, other: &S) -> bool {
|
||||
self.inner.eq_ignore_ascii_case(&other.as_ref().inner)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "box_from_os_str", since = "1.17.0")]
|
||||
|
|
|
@ -179,4 +179,34 @@ impl Slice {
|
|||
let rc = self.inner.into_rc();
|
||||
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn make_ascii_lowercase(&mut self) {
|
||||
self.inner.make_ascii_lowercase()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn make_ascii_uppercase(&mut self) {
|
||||
self.inner.make_ascii_uppercase()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_ascii_lowercase(&self) -> Buf {
|
||||
Buf { inner: self.inner.to_ascii_lowercase() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_ascii_uppercase(&self) -> Buf {
|
||||
Buf { inner: self.inner.to_ascii_uppercase() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_ascii(&self) -> bool {
|
||||
self.inner.is_ascii()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
|
||||
self.inner.eq_ignore_ascii_case(&other.inner)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use crate::sys::mutex::Mutex;
|
|||
use crate::sys::pipe::{self, AnonPipe};
|
||||
use crate::sys::stdio;
|
||||
use crate::sys_common::process::CommandEnv;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
use crate::sys_common::AsInner;
|
||||
|
||||
use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS};
|
||||
|
||||
|
@ -33,10 +33,9 @@ use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS};
|
|||
pub struct EnvKey(OsString);
|
||||
|
||||
impl From<OsString> for EnvKey {
|
||||
fn from(k: OsString) -> Self {
|
||||
let mut buf = k.into_inner().into_inner();
|
||||
buf.make_ascii_uppercase();
|
||||
EnvKey(FromInner::from_inner(FromInner::from_inner(buf)))
|
||||
fn from(mut k: OsString) -> Self {
|
||||
k.make_ascii_uppercase();
|
||||
EnvKey(k)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -195,6 +195,36 @@ impl Slice {
|
|||
let rc: Rc<[u8]> = Rc::from(&self.inner);
|
||||
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn make_ascii_lowercase(&mut self) {
|
||||
self.inner.make_ascii_lowercase()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn make_ascii_uppercase(&mut self) {
|
||||
self.inner.make_ascii_uppercase()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_ascii_lowercase(&self) -> Buf {
|
||||
Buf { inner: self.inner.to_ascii_lowercase() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_ascii_uppercase(&self) -> Buf {
|
||||
Buf { inner: self.inner.to_ascii_uppercase() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_ascii(&self) -> bool {
|
||||
self.inner.is_ascii()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
|
||||
self.inner.eq_ignore_ascii_case(&other.inner)
|
||||
}
|
||||
}
|
||||
|
||||
/// Platform-specific extensions to [`OsString`].
|
||||
|
|
|
@ -637,6 +637,36 @@ impl Wtf8 {
|
|||
let rc: Rc<[u8]> = Rc::from(&self.bytes);
|
||||
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn make_ascii_lowercase(&mut self) {
|
||||
self.bytes.make_ascii_lowercase()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn make_ascii_uppercase(&mut self) {
|
||||
self.bytes.make_ascii_uppercase()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
|
||||
Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
|
||||
Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_ascii(&self) -> bool {
|
||||
self.bytes.is_ascii()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
|
||||
self.bytes.eq_ignore_ascii_case(&other.bytes)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a slice of the given string for the byte range [`begin`..`end`).
|
||||
|
@ -837,12 +867,6 @@ impl Hash for Wtf8 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Wtf8 {
|
||||
pub fn make_ascii_uppercase(&mut self) {
|
||||
self.bytes.make_ascii_uppercase()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue