1212
1313//! Operations on ASCII strings and characters
1414
15- #![ unstable( feature = "std_misc" ,
16- reason = "unsure about placement and naming" ) ]
15+ #![ stable( feature = "rust1" , since = "1.0.0" ) ]
1716
18- use iter:: IteratorExt ;
19- use ops:: FnMut ;
20- use slice:: SliceExt ;
21- use str:: StrExt ;
22- use string:: String ;
23- use vec:: Vec ;
17+ use prelude:: v1:: * ;
18+
19+ use mem;
20+ use iter:: Range ;
2421
2522/// Extension methods for ASCII-subset only operations on owned strings
2623#[ unstable( feature = "std_misc" ,
@@ -38,52 +35,79 @@ pub trait OwnedAsciiExt {
3835}
3936
4037/// Extension methods for ASCII-subset only operations on string slices
41- #[ unstable( feature = "std_misc" ,
42- reason = "would prefer to do this in a more general way" ) ]
43- pub trait AsciiExt < T = Self > {
38+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
39+ pub trait AsciiExt {
40+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
41+ type Owned ;
42+
4443 /// Check if within the ASCII range.
44+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
4545 fn is_ascii ( & self ) -> bool ;
4646
4747 /// Makes a copy of the string in ASCII upper case:
4848 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
4949 /// but non-ASCII letters are unchanged.
50- fn to_ascii_uppercase ( & self ) -> T ;
50+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
51+ fn to_ascii_uppercase ( & self ) -> Self :: Owned ;
5152
5253 /// Makes a copy of the string in ASCII lower case:
5354 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
5455 /// but non-ASCII letters are unchanged.
55- fn to_ascii_lowercase ( & self ) -> T ;
56+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
57+ fn to_ascii_lowercase ( & self ) -> Self :: Owned ;
5658
5759 /// Check that two strings are an ASCII case-insensitive match.
5860 /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
5961 /// but without allocating and copying temporary strings.
62+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
6063 fn eq_ignore_ascii_case ( & self , other : & Self ) -> bool ;
64+
65+ /// Convert this type to its ASCII upper case equivalent in-place.
66+ ///
67+ /// See `to_ascii_uppercase` for more information.
68+ #[ unstable( feature = "ascii" ) ]
69+ fn make_ascii_uppercase ( & mut self ) ;
70+
71+ /// Convert this type to its ASCII lower case equivalent in-place.
72+ ///
73+ /// See `to_ascii_lowercase` for more information.
74+ #[ unstable( feature = "ascii" ) ]
75+ fn make_ascii_lowercase ( & mut self ) ;
6176}
6277
63- #[ unstable( feature = "std_misc" ,
64- reason = "would prefer to do this in a more general way" ) ]
65- impl AsciiExt < String > for str {
78+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
79+ impl AsciiExt for str {
80+ type Owned = String ;
81+
6682 #[ inline]
6783 fn is_ascii ( & self ) -> bool {
6884 self . bytes ( ) . all ( |b| b. is_ascii ( ) )
6985 }
7086
7187 #[ inline]
7288 fn to_ascii_uppercase ( & self ) -> String {
73- // Vec<u8>::to_ascii_uppercase() preserves the UTF-8 invariant.
74- unsafe { String :: from_utf8_unchecked ( self . as_bytes ( ) . to_ascii_uppercase ( ) ) }
89+ self . to_string ( ) . into_ascii_uppercase ( )
7590 }
7691
7792 #[ inline]
7893 fn to_ascii_lowercase ( & self ) -> String {
79- // Vec<u8>::to_ascii_lowercase() preserves the UTF-8 invariant.
80- unsafe { String :: from_utf8_unchecked ( self . as_bytes ( ) . to_ascii_lowercase ( ) ) }
94+ self . to_string ( ) . into_ascii_lowercase ( )
8195 }
8296
8397 #[ inline]
8498 fn eq_ignore_ascii_case ( & self , other : & str ) -> bool {
8599 self . as_bytes ( ) . eq_ignore_ascii_case ( other. as_bytes ( ) )
86100 }
101+
102+ fn make_ascii_uppercase ( & mut self ) {
103+ let me: & mut [ u8 ] = unsafe { mem:: transmute ( self ) } ;
104+ me. make_ascii_uppercase ( )
105+ }
106+
107+ fn make_ascii_lowercase ( & mut self ) {
108+ let me: & mut [ u8 ] = unsafe { mem:: transmute ( self ) } ;
109+ me. make_ascii_lowercase ( )
110+ }
87111}
88112
89113#[ unstable( feature = "std_misc" ,
@@ -102,22 +126,22 @@ impl OwnedAsciiExt for String {
102126 }
103127}
104128
105- #[ unstable ( feature = "std_misc" ,
106- reason = "would prefer to do this in a more general way" ) ]
107- impl AsciiExt < Vec < u8 > > for [ u8 ] {
129+ #[ stable ( feature = "rust1" , since = "1.0.0" ) ]
130+ impl AsciiExt for [ u8 ] {
131+ type Owned = Vec < u8 > ;
108132 #[ inline]
109133 fn is_ascii ( & self ) -> bool {
110134 self . iter ( ) . all ( |b| b. is_ascii ( ) )
111135 }
112136
113137 #[ inline]
114138 fn to_ascii_uppercase ( & self ) -> Vec < u8 > {
115- self . iter ( ) . map ( |b| b . to_ascii_uppercase ( ) ) . collect ( )
139+ self . to_vec ( ) . into_ascii_uppercase ( )
116140 }
117141
118142 #[ inline]
119143 fn to_ascii_lowercase ( & self ) -> Vec < u8 > {
120- self . iter ( ) . map ( |b| b . to_ascii_lowercase ( ) ) . collect ( )
144+ self . to_vec ( ) . into_ascii_lowercase ( )
121145 }
122146
123147 #[ inline]
@@ -127,55 +151,58 @@ impl AsciiExt<Vec<u8>> for [u8] {
127151 a. eq_ignore_ascii_case ( b)
128152 } )
129153 }
154+
155+ fn make_ascii_uppercase ( & mut self ) {
156+ for byte in self {
157+ byte. make_ascii_uppercase ( ) ;
158+ }
159+ }
160+
161+ fn make_ascii_lowercase ( & mut self ) {
162+ for byte in self {
163+ byte. make_ascii_lowercase ( ) ;
164+ }
165+ }
130166}
131167
132168#[ unstable( feature = "std_misc" ,
133169 reason = "would prefer to do this in a more general way" ) ]
134170impl OwnedAsciiExt for Vec < u8 > {
135171 #[ inline]
136172 fn into_ascii_uppercase ( mut self ) -> Vec < u8 > {
137- for byte in & mut self {
138- * byte = byte. to_ascii_uppercase ( ) ;
139- }
173+ self . make_ascii_uppercase ( ) ;
140174 self
141175 }
142176
143177 #[ inline]
144178 fn into_ascii_lowercase ( mut self ) -> Vec < u8 > {
145- for byte in & mut self {
146- * byte = byte. to_ascii_lowercase ( ) ;
147- }
179+ self . make_ascii_lowercase ( ) ;
148180 self
149181 }
150182}
151183
152- #[ unstable( feature = "std_misc" ,
153- reason = "would prefer to do this in a more general way" ) ]
184+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
154185impl AsciiExt for u8 {
186+ type Owned = u8 ;
155187 #[ inline]
156- fn is_ascii ( & self ) -> bool {
157- * self & 128 == 0u8
158- }
159-
188+ fn is_ascii ( & self ) -> bool { * self & 128 == 0u8 }
160189 #[ inline]
161- fn to_ascii_uppercase ( & self ) -> u8 {
162- ASCII_UPPERCASE_MAP [ * self as usize ]
163- }
164-
190+ fn to_ascii_uppercase ( & self ) -> u8 { ASCII_UPPERCASE_MAP [ * self as usize ] }
165191 #[ inline]
166- fn to_ascii_lowercase ( & self ) -> u8 {
167- ASCII_LOWERCASE_MAP [ * self as usize ]
168- }
169-
192+ fn to_ascii_lowercase ( & self ) -> u8 { ASCII_LOWERCASE_MAP [ * self as usize ] }
170193 #[ inline]
171194 fn eq_ignore_ascii_case ( & self , other : & u8 ) -> bool {
172195 self . to_ascii_lowercase ( ) == other. to_ascii_lowercase ( )
173196 }
197+ #[ inline]
198+ fn make_ascii_uppercase ( & mut self ) { * self = self . to_ascii_uppercase ( ) ; }
199+ #[ inline]
200+ fn make_ascii_lowercase ( & mut self ) { * self = self . to_ascii_lowercase ( ) ; }
174201}
175202
176- #[ unstable( feature = "std_misc" ,
177- reason = "would prefer to do this in a more general way" ) ]
203+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
178204impl AsciiExt for char {
205+ type Owned = char ;
179206 #[ inline]
180207 fn is_ascii ( & self ) -> bool {
181208 * self as u32 <= 0x7F
@@ -203,6 +230,19 @@ impl AsciiExt for char {
203230 fn eq_ignore_ascii_case ( & self , other : & char ) -> bool {
204231 self . to_ascii_lowercase ( ) == other. to_ascii_lowercase ( )
205232 }
233+
234+ #[ inline]
235+ fn make_ascii_uppercase ( & mut self ) { * self = self . to_ascii_uppercase ( ) ; }
236+ #[ inline]
237+ fn make_ascii_lowercase ( & mut self ) { * self = self . to_ascii_lowercase ( ) ; }
238+ }
239+
240+ /// An iterator over the escaped version of a byte, constructed via
241+ /// `std::ascii::escape_default`.
242+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
243+ pub struct EscapeDefault {
244+ range : Range < usize > ,
245+ data : [ u8 ; 4 ] ,
206246}
207247
208248/// Returns a 'default' ASCII and C++11-like literal escape of a `u8`
@@ -214,34 +254,46 @@ impl AsciiExt for char {
214254/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
215255/// - Single-quote, double-quote and backslash chars are backslash-escaped.
216256/// - Any other chars in the range [0x20,0x7e] are not escaped.
217- /// - Any other chars are given hex escapes.
257+ /// - Any other chars are given hex escapes of the form '\xNN' .
218258/// - Unicode escapes are never generated by this function.
219- #[ unstable( feature = "std_misc" ,
220- reason = "needs to be updated to use an iterator" ) ]
221- pub fn escape_default < F > ( c : u8 , mut f : F ) where
222- F : FnMut ( u8 ) ,
223- {
224- match c {
225- b'\t' => { f ( b'\\' ) ; f ( b't' ) ; }
226- b'\r' => { f ( b'\\' ) ; f ( b'r' ) ; }
227- b'\n' => { f ( b'\\' ) ; f ( b'n' ) ; }
228- b'\\' => { f ( b'\\' ) ; f ( b'\\' ) ; }
229- b'\'' => { f ( b'\\' ) ; f ( b'\'' ) ; }
230- b'"' => { f ( b'\\' ) ; f ( b'"' ) ; }
231- b'\x20' ... b'\x7e' => { f ( c) ; }
232- _ => {
233- f ( b'\\' ) ;
234- f ( b'x' ) ;
235- for & offset in & [ 4 u, 0 u] {
236- match ( ( c as i32 ) >> offset) & 0xf {
237- i @ 0 ... 9 => f ( b'0' + ( i as u8 ) ) ,
238- i => f ( b'a' + ( i as u8 - 10 ) ) ,
239- }
240- }
259+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
260+ pub fn escape_default ( c : u8 ) -> EscapeDefault {
261+ let ( data, len) = match c {
262+ b'\t' => ( [ b'\\' , b't' , 0 , 0 ] , 2 ) ,
263+ b'\r' => ( [ b'\\' , b'r' , 0 , 0 ] , 2 ) ,
264+ b'\n' => ( [ b'\\' , b'n' , 0 , 0 ] , 2 ) ,
265+ b'\\' => ( [ b'\\' , b'\\' , 0 , 0 ] , 2 ) ,
266+ b'\'' => ( [ b'\\' , b'\'' , 0 , 0 ] , 2 ) ,
267+ b'"' => ( [ b'\\' , b'"' , 0 , 0 ] , 2 ) ,
268+ b'\x20' ... b'\x7e' => ( [ c, 0 , 0 , 0 ] , 1 ) ,
269+ _ => ( [ b'\\' , b'x' , hexify ( c >> 4 ) , hexify ( c & 0xf ) ] , 4 ) ,
270+ } ;
271+
272+ return EscapeDefault { range : range ( 0 , len) , data : data } ;
273+
274+ fn hexify ( b : u8 ) -> u8 {
275+ match b {
276+ 0 ... 9 => b'0' + b,
277+ _ => b'a' + b - 10 ,
241278 }
242279 }
243280}
244281
282+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
283+ impl Iterator for EscapeDefault {
284+ type Item = u8 ;
285+ fn next ( & mut self ) -> Option < u8 > { self . range . next ( ) . map ( |i| self . data [ i] ) }
286+ fn size_hint ( & self ) -> ( usize , Option < usize > ) { self . range . size_hint ( ) }
287+ }
288+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
289+ impl DoubleEndedIterator for EscapeDefault {
290+ fn next_back ( & mut self ) -> Option < u8 > {
291+ self . range . next_back ( ) . map ( |i| self . data [ i] )
292+ }
293+ }
294+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
295+ impl ExactSizeIterator for EscapeDefault { }
296+
245297static ASCII_LOWERCASE_MAP : [ u8 ; 256 ] = [
246298 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
247299 0x08 , 0x09 , 0x0a , 0x0b , 0x0c , 0x0d , 0x0e , 0x0f ,
0 commit comments