From cc584d516697c8e058672e61a69f25dfa08bf688 Mon Sep 17 00:00:00 2001 From: TyPR124 Date: Wed, 11 Mar 2020 15:53:55 -0400 Subject: [PATCH 1/5] ascii methods on osstr --- src/libstd/ffi/os_str.rs | 143 ++++++++++++++++++++++++++ src/libstd/sys/windows/os_str.rs | 30 ++++++ src/libstd/sys_common/os_str_bytes.rs | 30 ++++++ src/libstd/sys_common/wtf8.rs | 36 +++++-- 4 files changed, 233 insertions(+), 6 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 0fbe8e5dd83e8..136ebc8f03f48 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -698,6 +698,149 @@ 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 = "none")] + 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 = "none")] + 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`]. + /// + /// # 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()); + /// ``` + /// + /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase + #[unstable(feature = "osstring_ascii", issue = "none")] + pub fn to_ascii_lowercase(&self) -> OsString { + // OsString::from_inner(Buf::from_inner(self.inner.inner.to_ascii_lowercase())) + 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`]. + /// + /// # 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()); + /// ``` + /// + /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase + #[unstable(feature = "osstring_ascii", issue = "none")] + pub fn to_ascii_uppercase(&self) -> OsString { + // OsString::from_inner(Buf::from_inner(self.inner.inner.to_ascii_lowercase())) + 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 = "none")] + 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 = "none")] + pub fn eq_ignore_ascii_case>(&self, other: &S) -> bool { + self.inner.eq_ignore_ascii_case(&other.as_ref().inner) + } } #[stable(feature = "box_from_os_str", since = "1.17.0")] diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index ff6885cb27477..6aab028873e07 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -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) + } } diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs index c5d02fb17722f..aa6cc33d831e0 100644 --- a/src/libstd/sys_common/os_str_bytes.rs +++ b/src/libstd/sys_common/os_str_bytes.rs @@ -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`]. diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 7509e1ee35dee..e9617dee6ac1f 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -645,6 +645,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`). @@ -845,12 +875,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::*; From 235700fea07555b54af003ad37310ef5c94a89e3 Mon Sep 17 00:00:00 2001 From: TyPR124 Date: Wed, 11 Mar 2020 16:05:11 -0400 Subject: [PATCH 2/5] use make_ascii_uppercase in windows/process.rs --- src/libstd/sys/windows/process.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index a62a637393ea3..77f9a5c9dc7b9 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -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 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) } } From 3781a1a2ac9947a02e1d38763d29a3fd752d4f6d Mon Sep 17 00:00:00 2001 From: TyPR124 Date: Wed, 11 Mar 2020 16:15:16 -0400 Subject: [PATCH 3/5] remove unnecessary comments --- src/libstd/ffi/os_str.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 136ebc8f03f48..039f55a18ca37 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -774,7 +774,6 @@ impl OsStr { /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase #[unstable(feature = "osstring_ascii", issue = "none")] pub fn to_ascii_lowercase(&self) -> OsString { - // OsString::from_inner(Buf::from_inner(self.inner.inner.to_ascii_lowercase())) OsString::from_inner(self.inner.to_ascii_lowercase()) } @@ -799,7 +798,6 @@ impl OsStr { /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase #[unstable(feature = "osstring_ascii", issue = "none")] pub fn to_ascii_uppercase(&self) -> OsString { - // OsString::from_inner(Buf::from_inner(self.inner.inner.to_ascii_lowercase())) OsString::from_inner(self.inner.to_ascii_uppercase()) } From ca4b40348e57c20d034b18395d9be25215e68643 Mon Sep 17 00:00:00 2001 From: TyPR124 Date: Thu, 12 Mar 2020 12:40:57 -0400 Subject: [PATCH 4/5] move doc links for consistency --- src/libstd/ffi/os_str.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 039f55a18ca37..d66d471a29e4b 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -761,6 +761,8 @@ impl OsStr { /// /// To lowercase the value in-place, use [`make_ascii_lowercase`]. /// + /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase + /// /// # Examples /// /// ``` @@ -770,8 +772,6 @@ impl OsStr { /// /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); /// ``` - /// - /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase #[unstable(feature = "osstring_ascii", issue = "none")] pub fn to_ascii_lowercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_lowercase()) @@ -785,6 +785,8 @@ impl OsStr { /// /// To uppercase the value in-place, use [`make_ascii_uppercase`]. /// + /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase + /// /// # Examples /// /// ``` @@ -794,8 +796,6 @@ impl OsStr { /// /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); /// ``` - /// - /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase #[unstable(feature = "osstring_ascii", issue = "none")] pub fn to_ascii_uppercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_uppercase()) From 271d43b158f71422df2239764d4d54734d4ebcfb Mon Sep 17 00:00:00 2001 From: TyPR124 Date: Sat, 28 Mar 2020 19:23:49 -0400 Subject: [PATCH 5/5] add tracking issue --- src/libstd/ffi/os_str.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index d66d471a29e4b..5e686946f8e9a 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -721,7 +721,7 @@ impl OsStr { /// /// assert_eq!("grÜße, jÜrgen ❤", s); /// ``` - #[unstable(feature = "osstring_ascii", issue = "none")] + #[unstable(feature = "osstring_ascii", issue = "70516")] pub fn make_ascii_lowercase(&mut self) { self.inner.make_ascii_lowercase() } @@ -748,7 +748,7 @@ impl OsStr { /// /// assert_eq!("GRüßE, JüRGEN ❤", s); /// ``` - #[unstable(feature = "osstring_ascii", issue = "none")] + #[unstable(feature = "osstring_ascii", issue = "70516")] pub fn make_ascii_uppercase(&mut self) { self.inner.make_ascii_uppercase() } @@ -772,7 +772,7 @@ impl OsStr { /// /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); /// ``` - #[unstable(feature = "osstring_ascii", issue = "none")] + #[unstable(feature = "osstring_ascii", issue = "70516")] pub fn to_ascii_lowercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_lowercase()) } @@ -796,7 +796,7 @@ impl OsStr { /// /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); /// ``` - #[unstable(feature = "osstring_ascii", issue = "none")] + #[unstable(feature = "osstring_ascii", issue = "70516")] pub fn to_ascii_uppercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_uppercase()) } @@ -815,7 +815,7 @@ impl OsStr { /// assert!(ascii.is_ascii()); /// assert!(!non_ascii.is_ascii()); /// ``` - #[unstable(feature = "osstring_ascii", issue = "none")] + #[unstable(feature = "osstring_ascii", issue = "70516")] pub fn is_ascii(&self) -> bool { self.inner.is_ascii() } @@ -835,7 +835,7 @@ impl OsStr { /// 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 = "none")] + #[unstable(feature = "osstring_ascii", issue = "70516")] pub fn eq_ignore_ascii_case>(&self, other: &S) -> bool { self.inner.eq_ignore_ascii_case(&other.as_ref().inner) }