From 6f01099ee0291b60ba053e9b29d4173573dcee68 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Sun, 25 May 2014 19:40:23 -0700 Subject: [PATCH 1/5] Make Vec.ptr() return the ptr field always Don't special-case zero-sized values in Vec.ptr(). Doing that prevents the following from working: // v is a Vec let newv = Vec::from_raw_parts(v.len(), v.cap(), v.mut_ptr()); mem::forget(v); Instead, teach slice::Items/MutItems to handle zero-sized values better. --- src/libcore/slice.rs | 32 +++++++++++++++++++------------- src/libstd/vec.rs | 17 ++--------------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 795dd389958ee..4f6b3d9b2ff4c 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1257,17 +1257,18 @@ macro_rules! iterator { if self.ptr == self.end { None } else { - let old = self.ptr; - self.ptr = if mem::size_of::() == 0 { + if mem::size_of::() == 0 { // purposefully don't use 'ptr.offset' because for // vectors with 0-size elements this would return the // same pointer. - transmute(self.ptr as uint + 1) + self.ptr = transmute(self.ptr as uint + 1); + Some(transmute(1u)) // Use a non-NULL pointer value } else { - self.ptr.offset(1) - }; + let old = self.ptr; + self.ptr = self.ptr.offset(1); - Some(transmute(old)) + Some(transmute(old)) + } } } } @@ -1289,13 +1290,14 @@ macro_rules! iterator { if self.end == self.ptr { None } else { - self.end = if mem::size_of::() == 0 { - // See above for why 'ptr.offset' isn't used - transmute(self.end as uint - 1) + if mem::size_of::() == 0 { + // See above for why `ptr.offset` isn't used + self.end = transmute(self.end as uint - 1); + Some(transmute(1u)) // Use a non-NULL pointer value } else { - self.end.offset(-1) - }; - Some(transmute(self.end)) + self.end = self.end.offset(-1); + Some(transmute(self.end)) + } } } } @@ -1314,7 +1316,11 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> { fn idx(&mut self, index: uint) -> Option<&'a T> { unsafe { if index < self.indexable() { - transmute(self.ptr.offset(index as int)) + if mem::size_of::() == 0 { + Some(transmute(1u)) // Use a non-NULL pointer value + } else { + Some(transmute(self.ptr.offset(index as int))) + } } else { None } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 81f6c7c7c9b7d..b039c67078e43 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -1184,15 +1184,7 @@ impl Vec { /// would also make any pointers to it invalid. #[inline] pub fn as_ptr(&self) -> *T { - // If we have a 0-sized vector, then the base pointer should not be NULL - // because an iterator over the slice will attempt to yield the base - // pointer as the first element in the vector, but this will end up - // being Some(NULL) which is optimized to None. - if mem::size_of::() == 0 { - 1 as *T - } else { - self.ptr as *T - } + self.ptr as *T } /// Returns a mutable unsafe pointer to the vector's buffer. @@ -1204,12 +1196,7 @@ impl Vec { /// would also make any pointers to it invalid. #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { - // see above for the 0-size check - if mem::size_of::() == 0 { - 1 as *mut T - } else { - self.ptr - } + self.ptr } /// Retains only the elements specified by the predicate. From 1f74e4ddcd26788ddcbee67c6459946b8ac2cdd4 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Sun, 25 May 2014 19:50:16 -0700 Subject: [PATCH 2/5] Add mod std::string::raw std::string::raw has one function, from_utf(), that converts a Vec to a String without testing for valid UTF-8. --- src/libstd/string.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libstd/string.rs b/src/libstd/string.rs index dce96cb2e8f32..8038cc0561026 100644 --- a/src/libstd/string.rs +++ b/src/libstd/string.rs @@ -366,6 +366,21 @@ impl FromStr for String { } } +/// Unsafe operations +pub mod raw { + use super::String; + use vec::Vec; + + /// Returns the vector as a string buffer without copying, + /// without checking if it contains valid UTF-8. + #[inline] + pub unsafe fn from_utf8(vec: Vec) -> String { + String { + vec: vec + } + } +} + #[cfg(test)] mod tests { extern crate test; From 1c5ac34afa6ac8b99e8ad0791a398c287a23cfe3 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Sun, 25 May 2014 21:01:20 -0700 Subject: [PATCH 3/5] Rename various things in std::ascii Rename a few traits in std::ascii to have more descriptive names. Also reimplement a few methods to avoid unnecessary allocation. And add a trait for Vec to do things like casemapping in-place. - Rename AsciiCast to ToAscii - Rename OwnedAsciiCast to IntoAscii - Split AsciiStr into two traits, the second called AsciiSlice - Add trait AsciiVec - Rename OwnedStrAsciiExt to StringAsciiExt This just barely qualifies as a breaking change. Every trait except StringAsciiExt is in the prelude. [breaking-change] --- src/etc/vim/syntax/rust.vim | 3 +- src/libstd/ascii.rs | 171 ++++++++++++++++++++++-------------- src/libstd/path/windows.rs | 2 +- src/libstd/prelude.rs | 4 +- 4 files changed, 108 insertions(+), 72 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 77348335eb346..b359c56cc3ba8 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -78,7 +78,8 @@ syn keyword rustEnumVariant Ok Err "syn keyword rustFunction drop " Types and traits {{{3 -syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr IntoBytes +syn keyword rustTrait Ascii ToAscii IntoAscii AsciiStr +syn keyword rustTrait AsciiSlice AsciiVec IntoBytes syn keyword rustTrait ToCStr syn keyword rustTrait Char syn keyword rustTrait Clone diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 75b31f9c35430..ce03a41fd7f52 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -15,11 +15,11 @@ use fmt; use iter::Iterator; use mem; use option::{Option, Some, None}; -use slice::{ImmutableVector, MutableVector, Vector}; -use str::{OwnedStr, Str, StrAllocating, StrSlice}; -use str; +use slice::{ImmutableVector, MutableVector, Vector, OwnedVector}; +use str::{Str, StrAllocating, StrSlice}; +use string; use string::String; -use to_str::{IntoStr}; +use to_str::IntoStr; use vec::Vec; /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. @@ -174,16 +174,20 @@ impl<'a> fmt::Show for Ascii { } } -/// Trait for converting into an ascii type. -pub trait AsciiCast { - /// Convert to an ascii type, fail on non-ASCII input. +/// Trait for converting a value into an ascii type. +pub trait ToAscii { + /// Coverts the receiver to an ascii type. + /// + /// # Failure + /// + /// Fails if the input is non-ASCII. #[inline] fn to_ascii(&self) -> T { assert!(self.is_ascii()); unsafe {self.to_ascii_nocheck()} } - /// Convert to an ascii type, return None on non-ASCII input. + /// Converts the receiver to an ascii type, returning `None` if non-ASCII. #[inline] fn to_ascii_opt(&self) -> Option { if self.is_ascii() { @@ -193,14 +197,14 @@ pub trait AsciiCast { } } - /// Convert to an ascii type, not doing any range asserts + /// Converts the receiver to an ascii type without range asserts. unsafe fn to_ascii_nocheck(&self) -> T; - /// Check if convertible to ascii + /// Checks if the receiver is convertable to an ascii type. fn is_ascii(&self) -> bool; } -impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] { +impl<'a> ToAscii<&'a[Ascii]> for &'a [u8] { #[inline] unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] { mem::transmute(*self) @@ -208,14 +212,11 @@ impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] { #[inline] fn is_ascii(&self) -> bool { - for b in self.iter() { - if !b.is_ascii() { return false; } - } - true + self.iter().all(|b| b.is_ascii()) } } -impl<'a> AsciiCast<&'a [Ascii]> for &'a str { +impl<'a> ToAscii<&'a [Ascii]> for &'a str { #[inline] unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] { mem::transmute(*self) @@ -227,7 +228,7 @@ impl<'a> AsciiCast<&'a [Ascii]> for &'a str { } } -impl AsciiCast for u8 { +impl ToAscii for u8 { #[inline] unsafe fn to_ascii_nocheck(&self) -> Ascii { Ascii{ chr: *self } @@ -239,7 +240,7 @@ impl AsciiCast for u8 { } } -impl AsciiCast for char { +impl ToAscii for char { #[inline] unsafe fn to_ascii_nocheck(&self) -> Ascii { Ascii{ chr: *self as u8 } @@ -247,23 +248,27 @@ impl AsciiCast for char { #[inline] fn is_ascii(&self) -> bool { - *self as u32 - ('\x7F' as u32 & *self as u32) == 0 + *self as u32 <= 0x7F } } /// Trait for copyless casting to an ascii vector. -pub trait OwnedAsciiCast { - /// Check if convertible to ascii +pub trait IntoAscii { + /// Checks if the receiver is convertible to ascii. fn is_ascii(&self) -> bool; - /// Take ownership and cast to an ascii vector. Fail on non-ASCII input. + /// Casts the receiver into an ascii vector. + /// + /// # Failure + /// + /// Fails if the input is non-ASCII. #[inline] fn into_ascii(self) -> Vec { assert!(self.is_ascii()); unsafe {self.into_ascii_nocheck()} } - /// Take ownership and cast to an ascii vector. Return None on non-ASCII input. + /// Casts the receiver into an ascii vector, returning `None` if non-ASCII. #[inline] fn into_ascii_opt(self) -> Option> { if self.is_ascii() { @@ -273,12 +278,11 @@ pub trait OwnedAsciiCast { } } - /// Take ownership and cast to an ascii vector. - /// Does not perform validation checks. + /// Casts the receiver into an ascii vector without range asserts. unsafe fn into_ascii_nocheck(self) -> Vec; } -impl OwnedAsciiCast for ~[u8] { +impl IntoAscii for ~[u8] { #[inline] fn is_ascii(&self) -> bool { self.as_slice().is_ascii() @@ -290,7 +294,7 @@ impl OwnedAsciiCast for ~[u8] { } } -impl OwnedAsciiCast for String { +impl IntoAscii for String { #[inline] fn is_ascii(&self) -> bool { self.as_slice().is_ascii() @@ -303,7 +307,7 @@ impl OwnedAsciiCast for String { } } -impl OwnedAsciiCast for Vec { +impl IntoAscii for Vec { #[inline] fn is_ascii(&self) -> bool { self.as_slice().is_ascii() @@ -315,28 +319,34 @@ impl OwnedAsciiCast for Vec { } } -/// Trait for converting an ascii type to a string. Needed to convert -/// `&[Ascii]` to `&str`. +/// Trait for interpreting an ASCII slice as a string. pub trait AsciiStr { - /// Convert to a string. - fn as_str_ascii<'a>(&'a self) -> &'a str; + /// Converts the receiver to a string slice. + fn as_str<'a>(&'a self) -> &'a str; +} + +impl<'a> AsciiStr for &'a [Ascii] { + #[inline] + fn as_str<'a>(&'a self) -> &'a str { + unsafe { mem::transmute(*self) } + } +} - /// Convert to vector representing a lower cased ascii string. +/// Trait for modifying an ASCII slice. +pub trait AsciiSlice { + /// Converts the receiver to a vector representation of a lowercase ASCII + /// string. fn to_lower(&self) -> Vec; - /// Convert to vector representing a upper cased ascii string. + /// Converts the receiver to a vector representation of an uppercase ASCII + /// string. fn to_upper(&self) -> Vec; - /// Compares two Ascii strings ignoring case. + /// Compares two ASCII strings ignoring case. fn eq_ignore_case(self, other: &[Ascii]) -> bool; } -impl<'a> AsciiStr for &'a [Ascii] { - #[inline] - fn as_str_ascii<'a>(&'a self) -> &'a str { - unsafe { mem::transmute(*self) } - } - +impl<'a> AsciiSlice for &'a [Ascii] { #[inline] fn to_lower(&self) -> Vec { self.iter().map(|a| a.to_lower()).collect() @@ -353,20 +363,52 @@ impl<'a> AsciiStr for &'a [Ascii] { } } +/// Trait for mutating an ASCII Vec. +pub trait AsciiVec { + /// Converts the receiver to a vector representation of a lowercase ASCII + /// string. + fn into_lower(self) -> Vec; + + /// Converts the receiver to a vector representation of an uppercase ASCII + /// string. + fn into_upper(self) -> Vec; +} + +impl AsciiVec for Vec { + #[inline] + fn into_lower(self) -> Vec { + let mut v = self; + for b in v.mut_iter() { + *b = b.to_lower() + } + v + } + + #[inline] + fn into_upper(self) -> Vec { + let mut v = self; + for b in v.mut_iter() { + *b = b.to_upper() + } + v + } +} + +// FIXME(#14433): This should be replaced with StrAllocating impl IntoStr for ~[Ascii] { #[inline] fn into_str(self) -> String { - let vector: Vec = self.as_slice().iter().map(|x| *x).collect(); + let vector: Vec = self.move_iter().collect(); vector.into_str() } } +// FIXME(#14433): This should be replaced with StrAllocating impl IntoStr for Vec { #[inline] fn into_str(self) -> String { unsafe { - let s: &str = mem::transmute(self.as_slice()); - s.to_string() + string::raw::from_utf8(mem::transmute(self)) } } } @@ -384,13 +426,15 @@ impl IntoBytes for Vec { } /// Extension methods for ASCII-subset only operations on owned strings -pub trait OwnedStrAsciiExt { - /// Convert the string to ASCII upper case: +pub trait StringAsciiExt { + /// Convert the string to ASCII upper case. + /// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', /// but non-ASCII letters are unchanged. fn into_ascii_upper(self) -> String; - /// Convert the string to ASCII lower case: + /// Convert the string to ASCII lower case. + /// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', /// but non-ASCII letters are unchanged. fn into_ascii_lower(self) -> String; @@ -398,17 +442,20 @@ pub trait OwnedStrAsciiExt { /// Extension methods for ASCII-subset only operations on string slices pub trait StrAsciiExt { - /// Makes a copy of the string in ASCII upper case: + /// Makes a copy of the string in ASCII upper case. + /// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', /// but non-ASCII letters are unchanged. fn to_ascii_upper(&self) -> String; - /// Makes a copy of the string in ASCII lower case: + /// Makes a copy of the string in ASCII lower case. + /// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', /// but non-ASCII letters are unchanged. fn to_ascii_lower(&self) -> String; /// Check that two strings are an ASCII case-insensitive match. + /// /// Same as `to_ascii_lower(a) == to_ascii_lower(b)`, /// but without allocating and copying temporary strings. fn eq_ignore_ascii_case(&self, other: &str) -> bool; @@ -417,12 +464,12 @@ pub trait StrAsciiExt { impl<'a> StrAsciiExt for &'a str { #[inline] fn to_ascii_upper(&self) -> String { - unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) } + unsafe { str_map_bytes(self.to_owned(), ASCII_UPPER_MAP) } } #[inline] fn to_ascii_lower(&self) -> String { - unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) } + unsafe { str_map_bytes(self.to_owned(), ASCII_LOWER_MAP) } } #[inline] @@ -436,7 +483,7 @@ impl<'a> StrAsciiExt for &'a str { } } -impl OwnedStrAsciiExt for String { +impl StringAsciiExt for String { #[inline] fn into_ascii_upper(self) -> String { unsafe { str_map_bytes(self, ASCII_UPPER_MAP) } @@ -449,23 +496,11 @@ impl OwnedStrAsciiExt for String { } #[inline] -unsafe fn str_map_bytes(string: String, map: &'static [u8]) -> String { - let mut bytes = string.into_bytes(); - - for b in bytes.mut_iter() { - *b = map[*b as uint]; - } - - str::from_utf8(bytes.as_slice()).unwrap().to_string() -} - -#[inline] -unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> String { - let mut s = string.to_string(); - for b in s.as_mut_bytes().mut_iter() { +unsafe fn str_map_bytes(mut string: String, map: &'static [u8]) -> String { + for b in string.as_mut_bytes().mut_iter() { *b = map[*b as uint]; } - s.into_string() + string } static ASCII_LOWER_MAP: &'static [u8] = &[ @@ -629,7 +664,7 @@ mod tests { #[test] fn test_ascii_as_str() { let v = v2ascii!([40, 32, 59]); - assert_eq!(v.as_str_ascii(), "( ;"); + assert_eq!(v.as_str(), "( ;"); } #[test] diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 88c3e9def8cf4..0acafb1838e5e 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -10,7 +10,7 @@ //! Windows file path handling -use ascii::AsciiCast; +use ascii::ToAscii; use c_str::{CString, ToCStr}; use clone::Clone; use cmp::{Eq, TotalEq}; diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 07aaeac64be1c..e8b24ab32ea7b 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -53,8 +53,8 @@ // Reexported types and traits -#[doc(no_inline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr}; -#[doc(no_inline)] pub use ascii::IntoBytes; +#[doc(no_inline)] pub use ascii::{Ascii, ToAscii, IntoAscii, AsciiStr}; +#[doc(no_inline)] pub use ascii::{AsciiSlice, AsciiVec, IntoBytes}; #[doc(no_inline)] pub use c_str::ToCStr; #[doc(no_inline)] pub use char::Char; #[doc(no_inline)] pub use clone::Clone; From 4521eb60d3d55d0aa168808782f84ee9779b6b37 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Sun, 25 May 2014 21:23:32 -0700 Subject: [PATCH 4/5] Rename more std::ascii methods for consistency Rename the various *_lower and *_upper methods to the equivalent *_lowercase and *_uppercase names. [breaking-change] --- src/libstd/ascii.rs | 153 ++++++++++++++++++++++++++++---------------- 1 file changed, 98 insertions(+), 55 deletions(-) diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index ce03a41fd7f52..ba9f8fb88b2ca 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -336,11 +336,25 @@ impl<'a> AsciiStr for &'a [Ascii] { pub trait AsciiSlice { /// Converts the receiver to a vector representation of a lowercase ASCII /// string. - fn to_lower(&self) -> Vec; + fn to_lowercase(&self) -> Vec; + + #[allow(missing_doc)] + #[deprecated = "replaced by .to_lowercase()"] + #[inline] + fn to_lower(&self) -> Vec { + self.to_lowercase() + } /// Converts the receiver to a vector representation of an uppercase ASCII /// string. - fn to_upper(&self) -> Vec; + fn to_uppercase(&self) -> Vec; + + #[allow(missing_doc)] + #[deprecated = "replaced by .to_uppercase()"] + #[inline] + fn to_upper(&self) -> Vec { + self.to_uppercase() + } /// Compares two ASCII strings ignoring case. fn eq_ignore_case(self, other: &[Ascii]) -> bool; @@ -348,13 +362,13 @@ pub trait AsciiSlice { impl<'a> AsciiSlice for &'a [Ascii] { #[inline] - fn to_lower(&self) -> Vec { - self.iter().map(|a| a.to_lower()).collect() + fn to_lowercase(&self) -> Vec { + self.iter().map(|a| a.to_lowercase()).collect() } #[inline] - fn to_upper(&self) -> Vec { - self.iter().map(|a| a.to_upper()).collect() + fn to_uppercase(&self) -> Vec { + self.iter().map(|a| a.to_uppercase()).collect() } #[inline] @@ -367,28 +381,28 @@ impl<'a> AsciiSlice for &'a [Ascii] { pub trait AsciiVec { /// Converts the receiver to a vector representation of a lowercase ASCII /// string. - fn into_lower(self) -> Vec; + fn into_lowercase(self) -> Vec; /// Converts the receiver to a vector representation of an uppercase ASCII /// string. - fn into_upper(self) -> Vec; + fn into_uppercase(self) -> Vec; } impl AsciiVec for Vec { #[inline] - fn into_lower(self) -> Vec { + fn into_lowercase(self) -> Vec { let mut v = self; for b in v.mut_iter() { - *b = b.to_lower() + *b = b.to_lowercase() } v } #[inline] - fn into_upper(self) -> Vec { + fn into_uppercase(self) -> Vec { let mut v = self; for b in v.mut_iter() { - *b = b.to_upper() + *b = b.to_uppercase() } v } @@ -431,13 +445,27 @@ pub trait StringAsciiExt { /// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', /// but non-ASCII letters are unchanged. - fn into_ascii_upper(self) -> String; + fn into_ascii_uppercase(self) -> String; + + #[allow(missing_doc)] + #[deprecated = "replaced by .into_ascii_uppercase"] + #[inline] + fn into_ascii_upper(self) -> String { + self.into_ascii_uppercase() + } /// Convert the string to ASCII lower case. /// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', /// but non-ASCII letters are unchanged. - fn into_ascii_lower(self) -> String; + fn into_ascii_lowercase(self) -> String; + + #[allow(missing_doc)] + #[deprecated = "replaced by .into_ascii_lowercase"] + #[inline] + fn into_ascii_lower(self) -> String { + self.into_ascii_lowercase() + } } /// Extension methods for ASCII-subset only operations on string slices @@ -446,29 +474,43 @@ pub trait StrAsciiExt { /// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', /// but non-ASCII letters are unchanged. - fn to_ascii_upper(&self) -> String; + fn to_ascii_uppercase(&self) -> String; + + #[allow(missing_doc)] + #[deprecated = "replaced by .to_ascii_uppercase()"] + #[inline] + fn to_ascii_upper(&self) -> String { + self.to_ascii_uppercase() + } /// Makes a copy of the string in ASCII lower case. /// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', /// but non-ASCII letters are unchanged. - fn to_ascii_lower(&self) -> String; + fn to_ascii_lowercase(&self) -> String; + + #[allow(missing_doc)] + #[deprecated = "replaced by .to_ascii_lowercase()"] + #[inline] + fn to_ascii_lower(&self) -> String { + self.to_ascii_lowercase() + } /// Check that two strings are an ASCII case-insensitive match. /// - /// Same as `to_ascii_lower(a) == to_ascii_lower(b)`, + /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, /// but without allocating and copying temporary strings. fn eq_ignore_ascii_case(&self, other: &str) -> bool; } impl<'a> StrAsciiExt for &'a str { #[inline] - fn to_ascii_upper(&self) -> String { + fn to_ascii_uppercase(&self) -> String { unsafe { str_map_bytes(self.to_owned(), ASCII_UPPER_MAP) } } #[inline] - fn to_ascii_lower(&self) -> String { + fn to_ascii_lowercase(&self) -> String { unsafe { str_map_bytes(self.to_owned(), ASCII_LOWER_MAP) } } @@ -485,12 +527,12 @@ impl<'a> StrAsciiExt for &'a str { impl StringAsciiExt for String { #[inline] - fn into_ascii_upper(self) -> String { + fn into_ascii_uppercase(self) -> String { unsafe { str_map_bytes(self, ASCII_UPPER_MAP) } } #[inline] - fn into_ascii_lower(self) -> String { + fn into_ascii_lowercase(self) -> String { unsafe { str_map_bytes(self, ASCII_LOWER_MAP) } } } @@ -599,15 +641,15 @@ mod tests { assert_eq!('A'.to_ascii().to_char(), 'A'); assert_eq!('A'.to_ascii().to_byte(), 65u8); - assert_eq!('A'.to_ascii().to_lower().to_char(), 'a'); - assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z'); - assert_eq!('a'.to_ascii().to_upper().to_char(), 'A'); - assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z'); + assert_eq!('A'.to_ascii().to_lowercase().to_char(), 'a'); + assert_eq!('Z'.to_ascii().to_lowercase().to_char(), 'z'); + assert_eq!('a'.to_ascii().to_uppercase().to_char(), 'A'); + assert_eq!('z'.to_ascii().to_uppercase().to_char(), 'Z'); - assert_eq!('@'.to_ascii().to_lower().to_char(), '@'); - assert_eq!('['.to_ascii().to_lower().to_char(), '['); - assert_eq!('`'.to_ascii().to_upper().to_char(), '`'); - assert_eq!('{'.to_ascii().to_upper().to_char(), '{'); + assert_eq!('@'.to_ascii().to_lowercase().to_char(), '@'); + assert_eq!('['.to_ascii().to_lowercase().to_char(), '['); + assert_eq!('`'.to_ascii().to_uppercase().to_char(), '`'); + assert_eq!('{'.to_ascii().to_uppercase().to_char(), '{'); assert!('0'.to_ascii().is_digit()); assert!('9'.to_ascii().is_digit()); @@ -631,12 +673,13 @@ mod tests { assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59])); assert_eq!("( ;".to_string().as_slice().to_ascii(), v2ascii!([40, 32, 59])); - assert_eq!("abCDef&?#".to_ascii().to_lower().into_str(), "abcdef&?#".to_string()); - assert_eq!("abCDef&?#".to_ascii().to_upper().into_str(), "ABCDEF&?#".to_string()); + assert_eq!("abCDef&?#".to_ascii().to_lowercase().into_str(), "abcdef&?#".to_string()); + assert_eq!("abCDef&?#".to_ascii().to_uppercase().into_str(), "ABCDEF&?#".to_string()); - assert_eq!("".to_ascii().to_lower().into_str(), "".to_string()); - assert_eq!("YMCA".to_ascii().to_lower().into_str(), "ymca".to_string()); - assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_str(), "ABCDEFXYZ:.;".to_string()); + assert_eq!("".to_ascii().into_lowercase().into_str(), "".to_string()); + assert_eq!("YMCA".to_ascii().into_lowercase().into_str(), "ymca".to_string()); + assert_eq!("abcDEFxyz:.;".to_ascii().into_uppercase().into_str(), + "ABCDEFXYZ:.;".to_string()); assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii())); @@ -648,11 +691,11 @@ mod tests { #[test] fn test_ascii_vec_ng() { - assert_eq!("abCDef&?#".to_ascii().to_lower().into_str(), "abcdef&?#".to_string()); - assert_eq!("abCDef&?#".to_ascii().to_upper().into_str(), "ABCDEF&?#".to_string()); - assert_eq!("".to_ascii().to_lower().into_str(), "".to_string()); - assert_eq!("YMCA".to_ascii().to_lower().into_str(), "ymca".to_string()); - assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_str(), "ABCDEFXYZ:.;".to_string()); + assert_eq!("abCDef&?#".to_ascii().to_lowercase().into_str(), "abcdef&?#".to_string()); + assert_eq!("abCDef&?#".to_ascii().to_uppercase().into_str(), "ABCDEF&?#".to_string()); + assert_eq!("".to_ascii().to_lowercase().into_str(), "".to_string()); + assert_eq!("YMCA".to_ascii().to_lowercase().into_str(), "ymca".to_string()); + assert_eq!("abcDEFxyz:.;".to_ascii().to_uppercase().into_str(), "ABCDEFXYZ:.;".to_string()); } #[test] @@ -722,64 +765,64 @@ mod tests { } #[test] - fn test_to_ascii_upper() { - assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), "URL()URL()URL()üRL".to_string()); - assert_eq!("hıKß".to_ascii_upper(), "HıKß".to_string()); + fn test_to_ascii_uppercase() { + assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL".to_string()); + assert_eq!("hıKß".to_ascii_uppercase(), "HıKß".to_string()); let mut i = 0; while i <= 500 { let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i }; - assert_eq!(from_char(from_u32(i).unwrap()).as_slice().to_ascii_upper(), + assert_eq!(from_char(from_u32(i).unwrap()).as_slice().to_ascii_uppercase(), from_char(from_u32(upper).unwrap()).to_string()) i += 1; } } #[test] - fn test_to_ascii_lower() { - assert_eq!("url()URL()uRl()Ürl".to_ascii_lower(), "url()url()url()Ürl".to_string()); + fn test_to_ascii_lowercase() { + assert_eq!("url()URL()uRl()Ürl".to_ascii_lowercase(), "url()url()url()Ürl".to_string()); // Dotted capital I, Kelvin sign, Sharp S. - assert_eq!("HİKß".to_ascii_lower(), "hİKß".to_string()); + assert_eq!("HİKß".to_ascii_lowercase(), "hİKß".to_string()); let mut i = 0; while i <= 500 { let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; - assert_eq!(from_char(from_u32(i).unwrap()).as_slice().to_ascii_lower(), + assert_eq!(from_char(from_u32(i).unwrap()).as_slice().to_ascii_lowercase(), from_char(from_u32(lower).unwrap()).to_string()) i += 1; } } #[test] - fn test_into_ascii_upper() { - assert_eq!(("url()URL()uRl()ürl".to_string()).into_ascii_upper(), + fn test_into_ascii_uppercase() { + assert_eq!(("url()URL()uRl()ürl".to_string()).into_ascii_uppercase(), "URL()URL()URL()üRL".to_string()); - assert_eq!(("hıKß".to_string()).into_ascii_upper(), "HıKß".to_string()); + assert_eq!(("hıKß".to_string()).into_ascii_uppercase(), "HıKß".to_string()); let mut i = 0; while i <= 500 { let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i }; - assert_eq!(from_char(from_u32(i).unwrap()).to_string().into_ascii_upper(), + assert_eq!(from_char(from_u32(i).unwrap()).to_string().into_ascii_uppercase(), from_char(from_u32(upper).unwrap()).to_string()) i += 1; } } #[test] - fn test_into_ascii_lower() { - assert_eq!(("url()URL()uRl()Ürl".to_string()).into_ascii_lower(), + fn test_into_ascii_lowercase() { + assert_eq!(("url()URL()uRl()Ürl".to_string()).into_ascii_lowercase(), "url()url()url()Ürl".to_string()); // Dotted capital I, Kelvin sign, Sharp S. - assert_eq!(("HİKß".to_string()).into_ascii_lower(), "hİKß".to_string()); + assert_eq!(("HİKß".to_string()).into_ascii_lowercase(), "hİKß".to_string()); let mut i = 0; while i <= 500 { let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; - assert_eq!(from_char(from_u32(i).unwrap()).to_string().into_ascii_lower(), + assert_eq!(from_char(from_u32(i).unwrap()).to_string().into_ascii_lowercase(), from_char(from_u32(lower).unwrap()).to_string()) i += 1; } From 954f52ec17c61adbf8ac427da1da69ba3c724449 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Sun, 25 May 2014 21:36:36 -0700 Subject: [PATCH 5/5] Update the various clients of ascii for the new names This includes updating for the previous rename of to_lower/upper on Ascii. --- src/compiletest/errors.rs | 3 ++- src/compiletest/runtest.rs | 15 +-------------- src/librustc/driver/config.rs | 3 ++- src/librustdoc/html/markdown.rs | 2 +- src/libstd/ascii.rs | 6 +++--- src/libstd/path/windows.rs | 12 ++++++------ src/libterm/terminfo/parm.rs | 7 +------ src/test/bench/shootout-k-nucleotide-pipes.rs | 2 +- src/test/bench/shootout-k-nucleotide.rs | 2 +- src/test/run-pass/issue-10683.rs | 2 +- 10 files changed, 19 insertions(+), 35 deletions(-) diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index c96e688c2900c..e401a7d920998 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::io::{BufferedReader, File}; +use std::ascii::StrAsciiExt; use regex::Regex; pub struct ExpectedError { @@ -31,7 +32,7 @@ pub fn load_errors(re: &Regex, testfile: &Path) -> Vec { fn parse_expected(line_num: uint, line: &str, re: &Regex) -> Option { re.captures(line).and_then(|caps| { let adjusts = caps.name("adjusts").len(); - let kind = caps.name("kind").to_ascii().to_lower().into_str().to_string(); + let kind = caps.name("kind").to_ascii_lowercase(); let msg = caps.name("msg").trim().to_string(); debug!("line={} kind={} msg={}", line_num, kind, msg); diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 8429e83a7aa43..4f71767629437 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -801,22 +801,9 @@ fn check_expected_errors(expected_errors: Vec , format!("{}:{}:", testfile.display(), ee.line) }).collect:: >(); - #[cfg(target_os = "win32")] - fn to_lower( s : &str ) -> String { - let i = s.chars(); - let c : Vec = i.map( |c| { - if c.is_ascii() { - c.to_ascii().to_lowercase().to_char() - } else { - c - } - } ).collect(); - str::from_chars(c.as_slice()).to_string() - } - #[cfg(target_os = "win32")] fn prefix_matches( line : &str, prefix : &str ) -> bool { - to_lower(line).as_slice().starts_with(to_lower(prefix).as_slice()) + line.len() >= prefix.len() && line.slice_to(prefix.len()).eq_ignore_ascii_case(prefix) } #[cfg(target_os = "linux")] diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index 16965bfa67fa8..7a867e813bfd0 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -36,6 +36,7 @@ use getopts::{optopt, optmulti, optflag, optflagopt}; use getopts; use lib::llvm::llvm; use std::cell::{RefCell}; +use std::ascii::StrAsciiExt; pub struct Config { @@ -596,7 +597,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let level_name = lint::level_to_str(*level); let level_short = level_name.slice_chars(0, 1); - let level_short = level_short.to_ascii().to_upper().into_str(); + let level_short = level_short.to_ascii_uppercase(); let flags = matches.opt_strs(level_short.as_slice()) .move_iter() .collect::>() diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index cafbbaa828bc7..1a61e60dadd73 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -207,7 +207,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { // Transform the contents of the header into a hyphenated string let id = (s.as_slice().words().map(|s| { match s.to_ascii_opt() { - Some(s) => s.to_lower().into_str().to_string(), + Some(s) => s.to_lowercase().into_str(), None => s.to_string() } }).collect::>().connect("-")).to_string(); diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index ba9f8fb88b2ca..0cdbf0ef860f0 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -676,9 +676,9 @@ mod tests { assert_eq!("abCDef&?#".to_ascii().to_lowercase().into_str(), "abcdef&?#".to_string()); assert_eq!("abCDef&?#".to_ascii().to_uppercase().into_str(), "ABCDEF&?#".to_string()); - assert_eq!("".to_ascii().into_lowercase().into_str(), "".to_string()); - assert_eq!("YMCA".to_ascii().into_lowercase().into_str(), "ymca".to_string()); - assert_eq!("abcDEFxyz:.;".to_ascii().into_uppercase().into_str(), + assert_eq!("".to_ascii().to_lowercase().into_str(), "".to_string()); + assert_eq!("YMCA".to_ascii().to_lowercase().into_str(), "ymca".to_string()); + assert_eq!("abcDEFxyz:.;".to_ascii().to_uppercase().into_str(), "ABCDEFXYZ:.;".to_string()); assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii())); diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 0acafb1838e5e..44e3a83ca9aa2 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -247,8 +247,8 @@ impl GenericPathUnsafe for Path { // path is assumed to have a prefix of Some(DiskPrefix) let repr = me.repr.as_slice(); match me.prefix { - Some(DiskPrefix) => repr[0] == path[0].to_ascii().to_upper().to_byte(), - Some(VerbatimDiskPrefix) => repr[4] == path[0].to_ascii().to_upper().to_byte(), + Some(DiskPrefix) => repr[0] == path[0].to_ascii().to_uppercase().to_byte(), + Some(VerbatimDiskPrefix) => repr[4] == path[0].to_ascii().to_uppercase().to_byte(), _ => false } } @@ -740,7 +740,7 @@ impl Path { let v = s.as_mut_vec(); *v.get_mut(0) = v.get(0) .to_ascii() - .to_upper() + .to_uppercase() .to_byte(); } if is_abs { @@ -756,7 +756,7 @@ impl Path { let mut s = String::from_str(s.slice_to(len)); unsafe { let v = s.as_mut_vec(); - *v.get_mut(4) = v.get(4).to_ascii().to_upper().to_byte(); + *v.get_mut(4) = v.get(4).to_ascii().to_uppercase().to_byte(); } Some(s) } @@ -777,12 +777,12 @@ impl Path { let mut s = String::with_capacity(n); match prefix { Some(DiskPrefix) => { - s.push_char(prefix_[0].to_ascii().to_upper().to_char()); + s.push_char(prefix_[0].to_ascii().to_uppercase().to_char()); s.push_char(':'); } Some(VerbatimDiskPrefix) => { s.push_str(prefix_.slice_to(4)); - s.push_char(prefix_[4].to_ascii().to_upper().to_char()); + s.push_char(prefix_[4].to_ascii().to_uppercase().to_char()); s.push_str(prefix_.slice_from(5)); } Some(UNCPrefix(a,b)) => { diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs index 3da8d7672f563..9dc553a527ee7 100644 --- a/src/libterm/terminfo/parm.rs +++ b/src/libterm/terminfo/parm.rs @@ -522,12 +522,7 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result ,String> { } } FormatHEX => { - s = s.as_slice() - .to_ascii() - .to_upper() - .into_bytes() - .move_iter() - .collect(); + s = s.as_slice().to_ascii().to_uppercase().into_bytes(); if flags.alternate { let s_ = replace(&mut s, vec!('0' as u8, 'X' as u8)); s.push_all_move(s_); diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index e39c51dd73a9f..f671f8185f25b 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -63,7 +63,7 @@ fn sort_and_fmt(mm: &HashMap , uint>, total: uint) -> String { buffer.push_str(format!("{} {:0.3f}\n", k.as_slice() .to_ascii() - .to_upper() + .to_uppercase() .into_str(), v).as_slice()); } diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 4b561def720c1..d666b1b260d71 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -257,7 +257,7 @@ fn get_sequence(r: &mut R, key: &str) -> Vec { res.push_all(l.as_slice().trim().as_bytes()); } for b in res.mut_iter() { - *b = b.to_ascii().to_upper().to_byte(); + *b = b.to_ascii().to_uppercase().to_byte(); } res } diff --git a/src/test/run-pass/issue-10683.rs b/src/test/run-pass/issue-10683.rs index 934adc07e2f15..3e0d7b47a705c 100644 --- a/src/test/run-pass/issue-10683.rs +++ b/src/test/run-pass/issue-10683.rs @@ -13,7 +13,7 @@ use std::ascii::StrAsciiExt; static NAME: &'static str = "hello world"; fn main() { - match NAME.to_ascii_lower().as_slice() { + match NAME.to_ascii_lowercase().as_slice() { "foo" => {} _ => {} }