12
12
13
13
//! Operations on ASCII strings and characters
14
14
15
- #![ unstable( feature = "std_misc" ,
16
- reason = "unsure about placement and naming" ) ]
15
+ #![ stable( feature = "rust1" , since = "1.0.0" ) ]
17
16
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 ;
24
21
25
22
/// Extension methods for ASCII-subset only operations on owned strings
26
23
#[ unstable( feature = "std_misc" ,
@@ -38,52 +35,79 @@ pub trait OwnedAsciiExt {
38
35
}
39
36
40
37
/// 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
+
44
43
/// Check if within the ASCII range.
44
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
45
45
fn is_ascii ( & self ) -> bool ;
46
46
47
47
/// Makes a copy of the string in ASCII upper case:
48
48
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
49
49
/// 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 ;
51
52
52
53
/// Makes a copy of the string in ASCII lower case:
53
54
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
54
55
/// 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 ;
56
58
57
59
/// Check that two strings are an ASCII case-insensitive match.
58
60
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
59
61
/// but without allocating and copying temporary strings.
62
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
60
63
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 ) ;
61
76
}
62
77
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
+
66
82
#[ inline]
67
83
fn is_ascii ( & self ) -> bool {
68
84
self . bytes ( ) . all ( |b| b. is_ascii ( ) )
69
85
}
70
86
71
87
#[ inline]
72
88
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 ( )
75
90
}
76
91
77
92
#[ inline]
78
93
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 ( )
81
95
}
82
96
83
97
#[ inline]
84
98
fn eq_ignore_ascii_case ( & self , other : & str ) -> bool {
85
99
self . as_bytes ( ) . eq_ignore_ascii_case ( other. as_bytes ( ) )
86
100
}
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
+ }
87
111
}
88
112
89
113
#[ unstable( feature = "std_misc" ,
@@ -102,22 +126,22 @@ impl OwnedAsciiExt for String {
102
126
}
103
127
}
104
128
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 > ;
108
132
#[ inline]
109
133
fn is_ascii ( & self ) -> bool {
110
134
self . iter ( ) . all ( |b| b. is_ascii ( ) )
111
135
}
112
136
113
137
#[ inline]
114
138
fn to_ascii_uppercase ( & self ) -> Vec < u8 > {
115
- self . iter ( ) . map ( |b| b . to_ascii_uppercase ( ) ) . collect ( )
139
+ self . to_vec ( ) . into_ascii_uppercase ( )
116
140
}
117
141
118
142
#[ inline]
119
143
fn to_ascii_lowercase ( & self ) -> Vec < u8 > {
120
- self . iter ( ) . map ( |b| b . to_ascii_lowercase ( ) ) . collect ( )
144
+ self . to_vec ( ) . into_ascii_lowercase ( )
121
145
}
122
146
123
147
#[ inline]
@@ -127,55 +151,58 @@ impl AsciiExt<Vec<u8>> for [u8] {
127
151
a. eq_ignore_ascii_case ( b)
128
152
} )
129
153
}
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
+ }
130
166
}
131
167
132
168
#[ unstable( feature = "std_misc" ,
133
169
reason = "would prefer to do this in a more general way" ) ]
134
170
impl OwnedAsciiExt for Vec < u8 > {
135
171
#[ inline]
136
172
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 ( ) ;
140
174
self
141
175
}
142
176
143
177
#[ inline]
144
178
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 ( ) ;
148
180
self
149
181
}
150
182
}
151
183
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" ) ]
154
185
impl AsciiExt for u8 {
186
+ type Owned = u8 ;
155
187
#[ inline]
156
- fn is_ascii ( & self ) -> bool {
157
- * self & 128 == 0u8
158
- }
159
-
188
+ fn is_ascii ( & self ) -> bool { * self & 128 == 0u8 }
160
189
#[ 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 ] }
165
191
#[ 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 ] }
170
193
#[ inline]
171
194
fn eq_ignore_ascii_case ( & self , other : & u8 ) -> bool {
172
195
self . to_ascii_lowercase ( ) == other. to_ascii_lowercase ( )
173
196
}
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 ( ) ; }
174
201
}
175
202
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" ) ]
178
204
impl AsciiExt for char {
205
+ type Owned = char ;
179
206
#[ inline]
180
207
fn is_ascii ( & self ) -> bool {
181
208
* self as u32 <= 0x7F
@@ -203,6 +230,19 @@ impl AsciiExt for char {
203
230
fn eq_ignore_ascii_case ( & self , other : & char ) -> bool {
204
231
self . to_ascii_lowercase ( ) == other. to_ascii_lowercase ( )
205
232
}
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 ] ,
206
246
}
207
247
208
248
/// Returns a 'default' ASCII and C++11-like literal escape of a `u8`
@@ -214,34 +254,46 @@ impl AsciiExt for char {
214
254
/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
215
255
/// - Single-quote, double-quote and backslash chars are backslash-escaped.
216
256
/// - 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' .
218
258
/// - 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 ,
241
278
}
242
279
}
243
280
}
244
281
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
+
245
297
static ASCII_LOWERCASE_MAP : [ u8 ; 256 ] = [
246
298
0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
247
299
0x08 , 0x09 , 0x0a , 0x0b , 0x0c , 0x0d , 0x0e , 0x0f ,
0 commit comments