]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
1a4d82fc JJ |
10 | |
11 | //! An owned, growable string that enforces that its contents are valid UTF-8. | |
12 | ||
85aaf69f | 13 | #![stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
14 | |
15 | use core::prelude::*; | |
16 | ||
1a4d82fc JJ |
17 | use core::fmt; |
18 | use core::hash; | |
9346a6ac | 19 | use core::iter::FromIterator; |
1a4d82fc JJ |
20 | use core::mem; |
21 | use core::ops::{self, Deref, Add, Index}; | |
22 | use core::ptr; | |
c34b1796 | 23 | use core::slice; |
9346a6ac | 24 | use core::str::pattern::Pattern; |
d9579d0f AL |
25 | use rustc_unicode::str as unicode_str; |
26 | use rustc_unicode::str::Utf16Item; | |
1a4d82fc | 27 | |
85aaf69f | 28 | use borrow::{Cow, IntoCow}; |
d9579d0f AL |
29 | use range::RangeArgument; |
30 | use str::{self, FromStr, Utf8Error, Chars}; | |
1a4d82fc JJ |
31 | use vec::{DerefVec, Vec, as_vec}; |
32 | ||
33 | /// A growable string stored as a UTF-8 encoded buffer. | |
34 | #[derive(Clone, PartialOrd, Eq, Ord)] | |
85aaf69f | 35 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
36 | pub struct String { |
37 | vec: Vec<u8>, | |
38 | } | |
39 | ||
40 | /// A possible error value from the `String::from_utf8` function. | |
85aaf69f SL |
41 | #[stable(feature = "rust1", since = "1.0.0")] |
42 | #[derive(Debug)] | |
1a4d82fc JJ |
43 | pub struct FromUtf8Error { |
44 | bytes: Vec<u8>, | |
45 | error: Utf8Error, | |
46 | } | |
47 | ||
48 | /// A possible error value from the `String::from_utf16` function. | |
85aaf69f SL |
49 | #[stable(feature = "rust1", since = "1.0.0")] |
50 | #[derive(Debug)] | |
1a4d82fc JJ |
51 | pub struct FromUtf16Error(()); |
52 | ||
53 | impl String { | |
54 | /// Creates a new string buffer initialized with the empty string. | |
55 | /// | |
56 | /// # Examples | |
57 | /// | |
58 | /// ``` | |
59 | /// let mut s = String::new(); | |
60 | /// ``` | |
61 | #[inline] | |
85aaf69f | 62 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
63 | pub fn new() -> String { |
64 | String { | |
65 | vec: Vec::new(), | |
66 | } | |
67 | } | |
68 | ||
69 | /// Creates a new string buffer with the given capacity. | |
70 | /// The string will be able to hold exactly `capacity` bytes without | |
71 | /// reallocating. If `capacity` is 0, the string will not allocate. | |
72 | /// | |
73 | /// # Examples | |
74 | /// | |
75 | /// ``` | |
76 | /// let mut s = String::with_capacity(10); | |
77 | /// ``` | |
78 | #[inline] | |
85aaf69f SL |
79 | #[stable(feature = "rust1", since = "1.0.0")] |
80 | pub fn with_capacity(capacity: usize) -> String { | |
1a4d82fc JJ |
81 | String { |
82 | vec: Vec::with_capacity(capacity), | |
83 | } | |
84 | } | |
85 | ||
86 | /// Creates a new string buffer from the given string. | |
87 | /// | |
88 | /// # Examples | |
89 | /// | |
90 | /// ``` | |
62682a34 SL |
91 | /// # #![feature(collections)] |
92 | /// let s = String::from("hello"); | |
c34b1796 | 93 | /// assert_eq!(&s[..], "hello"); |
1a4d82fc JJ |
94 | /// ``` |
95 | #[inline] | |
62682a34 SL |
96 | #[unstable(feature = "collections", reason = "use `String::from` instead")] |
97 | #[deprecated(since = "1.2.0", reason = "use `String::from` instead")] | |
c34b1796 | 98 | #[cfg(not(test))] |
1a4d82fc | 99 | pub fn from_str(string: &str) -> String { |
c34b1796 AL |
100 | String { vec: <[_]>::to_vec(string.as_bytes()) } |
101 | } | |
102 | ||
103 | // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is | |
104 | // required for this method definition, is not available. Since we don't | |
105 | // require this method for testing purposes, I'll just stub it | |
106 | // NB see the slice::hack module in slice.rs for more information | |
107 | #[inline] | |
108 | #[cfg(test)] | |
109 | pub fn from_str(_: &str) -> String { | |
110 | panic!("not available with cfg(test)"); | |
1a4d82fc JJ |
111 | } |
112 | ||
113 | /// Returns the vector as a string buffer, if possible, taking care not to | |
114 | /// copy it. | |
115 | /// | |
116 | /// # Failure | |
117 | /// | |
118 | /// If the given vector is not valid UTF-8, then the original vector and the | |
119 | /// corresponding error is returned. | |
120 | /// | |
121 | /// # Examples | |
122 | /// | |
c34b1796 | 123 | /// ``` |
1a4d82fc JJ |
124 | /// let hello_vec = vec![104, 101, 108, 108, 111]; |
125 | /// let s = String::from_utf8(hello_vec).unwrap(); | |
126 | /// assert_eq!(s, "hello"); | |
127 | /// | |
128 | /// let invalid_vec = vec![240, 144, 128]; | |
129 | /// let s = String::from_utf8(invalid_vec).err().unwrap(); | |
9346a6ac | 130 | /// let err = s.utf8_error(); |
c34b1796 | 131 | /// assert_eq!(s.into_bytes(), [240, 144, 128]); |
1a4d82fc JJ |
132 | /// ``` |
133 | #[inline] | |
85aaf69f | 134 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 135 | pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> { |
85aaf69f | 136 | match str::from_utf8(&vec) { |
1a4d82fc JJ |
137 | Ok(..) => Ok(String { vec: vec }), |
138 | Err(e) => Err(FromUtf8Error { bytes: vec, error: e }) | |
139 | } | |
140 | } | |
141 | ||
142 | /// Converts a vector of bytes to a new UTF-8 string. | |
143 | /// Any invalid UTF-8 sequences are replaced with U+FFFD REPLACEMENT CHARACTER. | |
144 | /// | |
145 | /// # Examples | |
146 | /// | |
c34b1796 | 147 | /// ``` |
1a4d82fc JJ |
148 | /// let input = b"Hello \xF0\x90\x80World"; |
149 | /// let output = String::from_utf8_lossy(input); | |
c34b1796 | 150 | /// assert_eq!(output, "Hello \u{FFFD}World"); |
1a4d82fc | 151 | /// ``` |
85aaf69f SL |
152 | #[stable(feature = "rust1", since = "1.0.0")] |
153 | pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> { | |
9346a6ac | 154 | let mut i; |
1a4d82fc JJ |
155 | match str::from_utf8(v) { |
156 | Ok(s) => return Cow::Borrowed(s), | |
9346a6ac | 157 | Err(e) => i = e.valid_up_to(), |
1a4d82fc JJ |
158 | } |
159 | ||
c34b1796 AL |
160 | const TAG_CONT_U8: u8 = 128; |
161 | const REPLACEMENT: &'static [u8] = b"\xEF\xBF\xBD"; // U+FFFD in UTF-8 | |
1a4d82fc | 162 | let total = v.len(); |
85aaf69f | 163 | fn unsafe_get(xs: &[u8], i: usize) -> u8 { |
1a4d82fc JJ |
164 | unsafe { *xs.get_unchecked(i) } |
165 | } | |
85aaf69f | 166 | fn safe_get(xs: &[u8], i: usize, total: usize) -> u8 { |
1a4d82fc JJ |
167 | if i >= total { |
168 | 0 | |
169 | } else { | |
170 | unsafe_get(xs, i) | |
171 | } | |
172 | } | |
173 | ||
174 | let mut res = String::with_capacity(total); | |
175 | ||
176 | if i > 0 { | |
177 | unsafe { | |
85aaf69f | 178 | res.as_mut_vec().push_all(&v[..i]) |
1a4d82fc JJ |
179 | }; |
180 | } | |
181 | ||
9346a6ac AL |
182 | // subseqidx is the index of the first byte of the subsequence we're |
183 | // looking at. It's used to copy a bunch of contiguous good codepoints | |
184 | // at once instead of copying them one by one. | |
1a4d82fc JJ |
185 | let mut subseqidx = i; |
186 | ||
187 | while i < total { | |
188 | let i_ = i; | |
189 | let byte = unsafe_get(v, i); | |
190 | i += 1; | |
191 | ||
192 | macro_rules! error { () => ({ | |
193 | unsafe { | |
194 | if subseqidx != i_ { | |
195 | res.as_mut_vec().push_all(&v[subseqidx..i_]); | |
196 | } | |
197 | subseqidx = i; | |
198 | res.as_mut_vec().push_all(REPLACEMENT); | |
199 | } | |
200 | })} | |
201 | ||
c34b1796 | 202 | if byte < 128 { |
1a4d82fc JJ |
203 | // subseqidx handles this |
204 | } else { | |
205 | let w = unicode_str::utf8_char_width(byte); | |
206 | ||
207 | match w { | |
208 | 2 => { | |
c34b1796 | 209 | if safe_get(v, i, total) & 192 != TAG_CONT_U8 { |
1a4d82fc JJ |
210 | error!(); |
211 | continue; | |
212 | } | |
213 | i += 1; | |
214 | } | |
215 | 3 => { | |
216 | match (byte, safe_get(v, i, total)) { | |
217 | (0xE0 , 0xA0 ... 0xBF) => (), | |
218 | (0xE1 ... 0xEC, 0x80 ... 0xBF) => (), | |
219 | (0xED , 0x80 ... 0x9F) => (), | |
220 | (0xEE ... 0xEF, 0x80 ... 0xBF) => (), | |
221 | _ => { | |
222 | error!(); | |
223 | continue; | |
224 | } | |
225 | } | |
226 | i += 1; | |
c34b1796 | 227 | if safe_get(v, i, total) & 192 != TAG_CONT_U8 { |
1a4d82fc JJ |
228 | error!(); |
229 | continue; | |
230 | } | |
231 | i += 1; | |
232 | } | |
233 | 4 => { | |
234 | match (byte, safe_get(v, i, total)) { | |
235 | (0xF0 , 0x90 ... 0xBF) => (), | |
236 | (0xF1 ... 0xF3, 0x80 ... 0xBF) => (), | |
237 | (0xF4 , 0x80 ... 0x8F) => (), | |
238 | _ => { | |
239 | error!(); | |
240 | continue; | |
241 | } | |
242 | } | |
243 | i += 1; | |
c34b1796 | 244 | if safe_get(v, i, total) & 192 != TAG_CONT_U8 { |
1a4d82fc JJ |
245 | error!(); |
246 | continue; | |
247 | } | |
248 | i += 1; | |
c34b1796 | 249 | if safe_get(v, i, total) & 192 != TAG_CONT_U8 { |
1a4d82fc JJ |
250 | error!(); |
251 | continue; | |
252 | } | |
253 | i += 1; | |
254 | } | |
255 | _ => { | |
256 | error!(); | |
257 | continue; | |
258 | } | |
259 | } | |
260 | } | |
261 | } | |
262 | if subseqidx < total { | |
263 | unsafe { | |
264 | res.as_mut_vec().push_all(&v[subseqidx..total]) | |
265 | }; | |
266 | } | |
267 | Cow::Owned(res) | |
268 | } | |
269 | ||
270 | /// Decode a UTF-16 encoded vector `v` into a `String`, returning `None` | |
271 | /// if `v` contains any invalid data. | |
272 | /// | |
273 | /// # Examples | |
274 | /// | |
c34b1796 | 275 | /// ``` |
1a4d82fc JJ |
276 | /// // 𝄞music |
277 | /// let mut v = &mut [0xD834, 0xDD1E, 0x006d, 0x0075, | |
278 | /// 0x0073, 0x0069, 0x0063]; | |
279 | /// assert_eq!(String::from_utf16(v).unwrap(), | |
280 | /// "𝄞music".to_string()); | |
281 | /// | |
282 | /// // 𝄞mu<invalid>ic | |
283 | /// v[4] = 0xD800; | |
284 | /// assert!(String::from_utf16(v).is_err()); | |
285 | /// ``` | |
85aaf69f | 286 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
287 | pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> { |
288 | let mut s = String::with_capacity(v.len()); | |
289 | for c in unicode_str::utf16_items(v) { | |
290 | match c { | |
291 | Utf16Item::ScalarValue(c) => s.push(c), | |
292 | Utf16Item::LoneSurrogate(_) => return Err(FromUtf16Error(())), | |
293 | } | |
294 | } | |
295 | Ok(s) | |
296 | } | |
297 | ||
298 | /// Decode a UTF-16 encoded vector `v` into a string, replacing | |
299 | /// invalid data with the replacement character (U+FFFD). | |
300 | /// | |
301 | /// # Examples | |
302 | /// | |
c34b1796 | 303 | /// ``` |
1a4d82fc JJ |
304 | /// // 𝄞mus<invalid>ic<invalid> |
305 | /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, | |
306 | /// 0x0073, 0xDD1E, 0x0069, 0x0063, | |
307 | /// 0xD834]; | |
308 | /// | |
309 | /// assert_eq!(String::from_utf16_lossy(v), | |
310 | /// "𝄞mus\u{FFFD}ic\u{FFFD}".to_string()); | |
311 | /// ``` | |
85aaf69f SL |
312 | #[inline] |
313 | #[stable(feature = "rust1", since = "1.0.0")] | |
1a4d82fc JJ |
314 | pub fn from_utf16_lossy(v: &[u16]) -> String { |
315 | unicode_str::utf16_items(v).map(|c| c.to_char_lossy()).collect() | |
316 | } | |
317 | ||
318 | /// Creates a new `String` from a length, capacity, and pointer. | |
319 | /// | |
320 | /// This is unsafe because: | |
c34b1796 | 321 | /// |
1a4d82fc JJ |
322 | /// * We call `Vec::from_raw_parts` to get a `Vec<u8>`; |
323 | /// * We assume that the `Vec` contains valid UTF-8. | |
324 | #[inline] | |
85aaf69f SL |
325 | #[stable(feature = "rust1", since = "1.0.0")] |
326 | pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { | |
1a4d82fc JJ |
327 | String { |
328 | vec: Vec::from_raw_parts(buf, length, capacity), | |
329 | } | |
330 | } | |
331 | ||
332 | /// Converts a vector of bytes to a new `String` without checking if | |
333 | /// it contains valid UTF-8. This is unsafe because it assumes that | |
334 | /// the UTF-8-ness of the vector has already been validated. | |
335 | #[inline] | |
85aaf69f | 336 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
337 | pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String { |
338 | String { vec: bytes } | |
339 | } | |
340 | ||
9346a6ac | 341 | /// Returns the underlying byte buffer, encoded as UTF-8. |
1a4d82fc JJ |
342 | /// |
343 | /// # Examples | |
344 | /// | |
345 | /// ``` | |
62682a34 | 346 | /// let s = String::from("hello"); |
1a4d82fc | 347 | /// let bytes = s.into_bytes(); |
c34b1796 | 348 | /// assert_eq!(bytes, [104, 101, 108, 108, 111]); |
1a4d82fc JJ |
349 | /// ``` |
350 | #[inline] | |
85aaf69f | 351 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
352 | pub fn into_bytes(self) -> Vec<u8> { |
353 | self.vec | |
354 | } | |
355 | ||
9346a6ac | 356 | /// Extracts a string slice containing the entire string. |
c34b1796 AL |
357 | #[inline] |
358 | #[unstable(feature = "convert", | |
359 | reason = "waiting on RFC revision")] | |
360 | pub fn as_str(&self) -> &str { | |
361 | self | |
362 | } | |
363 | ||
1a4d82fc JJ |
364 | /// Pushes the given string onto this string buffer. |
365 | /// | |
366 | /// # Examples | |
367 | /// | |
368 | /// ``` | |
62682a34 | 369 | /// let mut s = String::from("foo"); |
1a4d82fc | 370 | /// s.push_str("bar"); |
c34b1796 | 371 | /// assert_eq!(s, "foobar"); |
1a4d82fc JJ |
372 | /// ``` |
373 | #[inline] | |
85aaf69f | 374 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
375 | pub fn push_str(&mut self, string: &str) { |
376 | self.vec.push_all(string.as_bytes()) | |
377 | } | |
378 | ||
379 | /// Returns the number of bytes that this string buffer can hold without | |
380 | /// reallocating. | |
381 | /// | |
382 | /// # Examples | |
383 | /// | |
384 | /// ``` | |
385 | /// let s = String::with_capacity(10); | |
386 | /// assert!(s.capacity() >= 10); | |
387 | /// ``` | |
388 | #[inline] | |
85aaf69f SL |
389 | #[stable(feature = "rust1", since = "1.0.0")] |
390 | pub fn capacity(&self) -> usize { | |
1a4d82fc JJ |
391 | self.vec.capacity() |
392 | } | |
393 | ||
394 | /// Reserves capacity for at least `additional` more bytes to be inserted | |
395 | /// in the given `String`. The collection may reserve more space to avoid | |
396 | /// frequent reallocations. | |
397 | /// | |
398 | /// # Panics | |
399 | /// | |
85aaf69f | 400 | /// Panics if the new capacity overflows `usize`. |
1a4d82fc JJ |
401 | /// |
402 | /// # Examples | |
403 | /// | |
404 | /// ``` | |
405 | /// let mut s = String::new(); | |
406 | /// s.reserve(10); | |
407 | /// assert!(s.capacity() >= 10); | |
408 | /// ``` | |
409 | #[inline] | |
85aaf69f SL |
410 | #[stable(feature = "rust1", since = "1.0.0")] |
411 | pub fn reserve(&mut self, additional: usize) { | |
1a4d82fc JJ |
412 | self.vec.reserve(additional) |
413 | } | |
414 | ||
415 | /// Reserves the minimum capacity for exactly `additional` more bytes to be | |
416 | /// inserted in the given `String`. Does nothing if the capacity is already | |
417 | /// sufficient. | |
418 | /// | |
419 | /// Note that the allocator may give the collection more space than it | |
420 | /// requests. Therefore capacity can not be relied upon to be precisely | |
421 | /// minimal. Prefer `reserve` if future insertions are expected. | |
422 | /// | |
423 | /// # Panics | |
424 | /// | |
85aaf69f | 425 | /// Panics if the new capacity overflows `usize`. |
1a4d82fc JJ |
426 | /// |
427 | /// # Examples | |
428 | /// | |
429 | /// ``` | |
430 | /// let mut s = String::new(); | |
62682a34 | 431 | /// s.reserve_exact(10); |
1a4d82fc JJ |
432 | /// assert!(s.capacity() >= 10); |
433 | /// ``` | |
434 | #[inline] | |
85aaf69f SL |
435 | #[stable(feature = "rust1", since = "1.0.0")] |
436 | pub fn reserve_exact(&mut self, additional: usize) { | |
1a4d82fc JJ |
437 | self.vec.reserve_exact(additional) |
438 | } | |
439 | ||
440 | /// Shrinks the capacity of this string buffer to match its length. | |
441 | /// | |
442 | /// # Examples | |
443 | /// | |
444 | /// ``` | |
62682a34 | 445 | /// let mut s = String::from("foo"); |
1a4d82fc JJ |
446 | /// s.reserve(100); |
447 | /// assert!(s.capacity() >= 100); | |
448 | /// s.shrink_to_fit(); | |
449 | /// assert_eq!(s.capacity(), 3); | |
450 | /// ``` | |
451 | #[inline] | |
85aaf69f | 452 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
453 | pub fn shrink_to_fit(&mut self) { |
454 | self.vec.shrink_to_fit() | |
455 | } | |
456 | ||
457 | /// Adds the given character to the end of the string. | |
458 | /// | |
459 | /// # Examples | |
460 | /// | |
461 | /// ``` | |
62682a34 | 462 | /// let mut s = String::from("abc"); |
1a4d82fc JJ |
463 | /// s.push('1'); |
464 | /// s.push('2'); | |
465 | /// s.push('3'); | |
c34b1796 | 466 | /// assert_eq!(s, "abc123"); |
1a4d82fc JJ |
467 | /// ``` |
468 | #[inline] | |
85aaf69f | 469 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 470 | pub fn push(&mut self, ch: char) { |
62682a34 SL |
471 | match ch.len_utf8() { |
472 | 1 => self.vec.push(ch as u8), | |
473 | ch_len => { | |
474 | let cur_len = self.len(); | |
475 | // This may use up to 4 bytes. | |
476 | self.vec.reserve(ch_len); | |
1a4d82fc | 477 | |
62682a34 SL |
478 | unsafe { |
479 | // Attempt to not use an intermediate buffer by just pushing bytes | |
480 | // directly onto this string. | |
481 | let slice = slice::from_raw_parts_mut ( | |
482 | self.vec.as_mut_ptr().offset(cur_len as isize), | |
483 | ch_len | |
484 | ); | |
485 | let used = ch.encode_utf8(slice).unwrap_or(0); | |
486 | self.vec.set_len(cur_len + used); | |
487 | } | |
488 | } | |
1a4d82fc JJ |
489 | } |
490 | } | |
491 | ||
492 | /// Works with the underlying buffer as a byte slice. | |
493 | /// | |
494 | /// # Examples | |
495 | /// | |
496 | /// ``` | |
62682a34 SL |
497 | /// let s = String::from("hello"); |
498 | /// assert_eq!(s.as_bytes(), [104, 101, 108, 108, 111]); | |
1a4d82fc JJ |
499 | /// ``` |
500 | #[inline] | |
85aaf69f SL |
501 | #[stable(feature = "rust1", since = "1.0.0")] |
502 | pub fn as_bytes(&self) -> &[u8] { | |
503 | &self.vec | |
1a4d82fc JJ |
504 | } |
505 | ||
506 | /// Shortens a string to the specified length. | |
507 | /// | |
508 | /// # Panics | |
509 | /// | |
510 | /// Panics if `new_len` > current length, | |
511 | /// or if `new_len` is not a character boundary. | |
512 | /// | |
513 | /// # Examples | |
514 | /// | |
515 | /// ``` | |
62682a34 | 516 | /// let mut s = String::from("hello"); |
1a4d82fc | 517 | /// s.truncate(2); |
c34b1796 | 518 | /// assert_eq!(s, "he"); |
1a4d82fc JJ |
519 | /// ``` |
520 | #[inline] | |
85aaf69f SL |
521 | #[stable(feature = "rust1", since = "1.0.0")] |
522 | pub fn truncate(&mut self, new_len: usize) { | |
1a4d82fc JJ |
523 | assert!(self.is_char_boundary(new_len)); |
524 | self.vec.truncate(new_len) | |
525 | } | |
526 | ||
527 | /// Removes the last character from the string buffer and returns it. | |
528 | /// Returns `None` if this string buffer is empty. | |
529 | /// | |
530 | /// # Examples | |
531 | /// | |
532 | /// ``` | |
62682a34 | 533 | /// let mut s = String::from("foo"); |
1a4d82fc JJ |
534 | /// assert_eq!(s.pop(), Some('o')); |
535 | /// assert_eq!(s.pop(), Some('o')); | |
536 | /// assert_eq!(s.pop(), Some('f')); | |
537 | /// assert_eq!(s.pop(), None); | |
538 | /// ``` | |
539 | #[inline] | |
85aaf69f | 540 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
541 | pub fn pop(&mut self) -> Option<char> { |
542 | let len = self.len(); | |
543 | if len == 0 { | |
544 | return None | |
545 | } | |
546 | ||
c34b1796 | 547 | let ch = self.char_at_reverse(len); |
1a4d82fc | 548 | unsafe { |
c34b1796 | 549 | self.vec.set_len(len - ch.len_utf8()); |
1a4d82fc JJ |
550 | } |
551 | Some(ch) | |
552 | } | |
553 | ||
554 | /// Removes the character from the string buffer at byte position `idx` and | |
555 | /// returns it. | |
556 | /// | |
557 | /// # Warning | |
558 | /// | |
559 | /// This is an O(n) operation as it requires copying every element in the | |
560 | /// buffer. | |
561 | /// | |
562 | /// # Panics | |
563 | /// | |
564 | /// If `idx` does not lie on a character boundary, or if it is out of | |
565 | /// bounds, then this function will panic. | |
566 | /// | |
567 | /// # Examples | |
568 | /// | |
569 | /// ``` | |
62682a34 | 570 | /// let mut s = String::from("foo"); |
1a4d82fc JJ |
571 | /// assert_eq!(s.remove(0), 'f'); |
572 | /// assert_eq!(s.remove(1), 'o'); | |
573 | /// assert_eq!(s.remove(0), 'o'); | |
574 | /// ``` | |
85aaf69f SL |
575 | #[inline] |
576 | #[stable(feature = "rust1", since = "1.0.0")] | |
577 | pub fn remove(&mut self, idx: usize) -> char { | |
1a4d82fc JJ |
578 | let len = self.len(); |
579 | assert!(idx <= len); | |
580 | ||
c34b1796 AL |
581 | let ch = self.char_at(idx); |
582 | let next = idx + ch.len_utf8(); | |
1a4d82fc | 583 | unsafe { |
c34b1796 AL |
584 | ptr::copy(self.vec.as_ptr().offset(next as isize), |
585 | self.vec.as_mut_ptr().offset(idx as isize), | |
586 | len - next); | |
1a4d82fc JJ |
587 | self.vec.set_len(len - (next - idx)); |
588 | } | |
589 | ch | |
590 | } | |
591 | ||
9346a6ac | 592 | /// Inserts a character into the string buffer at byte position `idx`. |
1a4d82fc JJ |
593 | /// |
594 | /// # Warning | |
595 | /// | |
596 | /// This is an O(n) operation as it requires copying every element in the | |
597 | /// buffer. | |
598 | /// | |
599 | /// # Panics | |
600 | /// | |
601 | /// If `idx` does not lie on a character boundary or is out of bounds, then | |
602 | /// this function will panic. | |
85aaf69f SL |
603 | #[inline] |
604 | #[stable(feature = "rust1", since = "1.0.0")] | |
605 | pub fn insert(&mut self, idx: usize, ch: char) { | |
1a4d82fc JJ |
606 | let len = self.len(); |
607 | assert!(idx <= len); | |
608 | assert!(self.is_char_boundary(idx)); | |
609 | self.vec.reserve(4); | |
610 | let mut bits = [0; 4]; | |
611 | let amt = ch.encode_utf8(&mut bits).unwrap(); | |
612 | ||
613 | unsafe { | |
c34b1796 AL |
614 | ptr::copy(self.vec.as_ptr().offset(idx as isize), |
615 | self.vec.as_mut_ptr().offset((idx + amt) as isize), | |
616 | len - idx); | |
617 | ptr::copy(bits.as_ptr(), | |
618 | self.vec.as_mut_ptr().offset(idx as isize), | |
619 | amt); | |
1a4d82fc JJ |
620 | self.vec.set_len(len + amt); |
621 | } | |
622 | } | |
623 | ||
624 | /// Views the string buffer as a mutable sequence of bytes. | |
625 | /// | |
626 | /// This is unsafe because it does not check | |
627 | /// to ensure that the resulting string will be valid UTF-8. | |
628 | /// | |
629 | /// # Examples | |
630 | /// | |
631 | /// ``` | |
62682a34 | 632 | /// let mut s = String::from("hello"); |
1a4d82fc JJ |
633 | /// unsafe { |
634 | /// let vec = s.as_mut_vec(); | |
c34b1796 | 635 | /// assert!(vec == &[104, 101, 108, 108, 111]); |
1a4d82fc JJ |
636 | /// vec.reverse(); |
637 | /// } | |
c34b1796 | 638 | /// assert_eq!(s, "olleh"); |
1a4d82fc | 639 | /// ``` |
85aaf69f SL |
640 | #[inline] |
641 | #[stable(feature = "rust1", since = "1.0.0")] | |
642 | pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> { | |
1a4d82fc JJ |
643 | &mut self.vec |
644 | } | |
645 | ||
9346a6ac | 646 | /// Returns the number of bytes in this string. |
1a4d82fc JJ |
647 | /// |
648 | /// # Examples | |
649 | /// | |
650 | /// ``` | |
651 | /// let a = "foo".to_string(); | |
652 | /// assert_eq!(a.len(), 3); | |
653 | /// ``` | |
654 | #[inline] | |
85aaf69f SL |
655 | #[stable(feature = "rust1", since = "1.0.0")] |
656 | pub fn len(&self) -> usize { self.vec.len() } | |
1a4d82fc JJ |
657 | |
658 | /// Returns true if the string contains no bytes | |
659 | /// | |
660 | /// # Examples | |
661 | /// | |
662 | /// ``` | |
663 | /// let mut v = String::new(); | |
664 | /// assert!(v.is_empty()); | |
665 | /// v.push('a'); | |
666 | /// assert!(!v.is_empty()); | |
667 | /// ``` | |
85aaf69f SL |
668 | #[inline] |
669 | #[stable(feature = "rust1", since = "1.0.0")] | |
1a4d82fc JJ |
670 | pub fn is_empty(&self) -> bool { self.len() == 0 } |
671 | ||
672 | /// Truncates the string, returning it to 0 length. | |
673 | /// | |
674 | /// # Examples | |
675 | /// | |
676 | /// ``` | |
677 | /// let mut s = "foo".to_string(); | |
678 | /// s.clear(); | |
679 | /// assert!(s.is_empty()); | |
680 | /// ``` | |
681 | #[inline] | |
85aaf69f | 682 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
683 | pub fn clear(&mut self) { |
684 | self.vec.clear() | |
685 | } | |
d9579d0f AL |
686 | |
687 | /// Create a draining iterator that removes the specified range in the string | |
688 | /// and yields the removed chars from start to end. The element range is | |
689 | /// removed even if the iterator is not consumed until the end. | |
690 | /// | |
691 | /// # Panics | |
692 | /// | |
693 | /// Panics if the starting point or end point are not on character boundaries, | |
694 | /// or if they are out of bounds. | |
695 | /// | |
696 | /// # Examples | |
697 | /// | |
698 | /// ``` | |
62682a34 | 699 | /// # #![feature(drain)] |
d9579d0f AL |
700 | /// |
701 | /// let mut s = String::from("α is alpha, β is beta"); | |
702 | /// let beta_offset = s.find('β').unwrap_or(s.len()); | |
703 | /// | |
704 | /// // Remove the range up until the β from the string | |
705 | /// let t: String = s.drain(..beta_offset).collect(); | |
706 | /// assert_eq!(t, "α is alpha, "); | |
707 | /// assert_eq!(s, "β is beta"); | |
708 | /// | |
709 | /// // A full range clears the string | |
710 | /// s.drain(..); | |
711 | /// assert_eq!(s, ""); | |
712 | /// ``` | |
62682a34 | 713 | #[unstable(feature = "drain", |
d9579d0f AL |
714 | reason = "recently added, matches RFC")] |
715 | pub fn drain<R>(&mut self, range: R) -> Drain where R: RangeArgument<usize> { | |
716 | // Memory safety | |
717 | // | |
718 | // The String version of Drain does not have the memory safety issues | |
719 | // of the vector version. The data is just plain bytes. | |
720 | // Because the range removal happens in Drop, if the Drain iterator is leaked, | |
721 | // the removal will not happen. | |
722 | let len = self.len(); | |
723 | let start = *range.start().unwrap_or(&0); | |
724 | let end = *range.end().unwrap_or(&len); | |
725 | ||
726 | // Take out two simultaneous borrows. The &mut String won't be accessed | |
727 | // until iteration is over, in Drop. | |
728 | let self_ptr = self as *mut _; | |
729 | // slicing does the appropriate bounds checks | |
730 | let chars_iter = self[start..end].chars(); | |
731 | ||
732 | Drain { | |
733 | start: start, | |
734 | end: end, | |
735 | iter: chars_iter, | |
736 | string: self_ptr, | |
737 | } | |
738 | } | |
1a4d82fc JJ |
739 | } |
740 | ||
741 | impl FromUtf8Error { | |
9346a6ac | 742 | /// Consumes this error, returning the bytes that were attempted to make a |
1a4d82fc | 743 | /// `String` with. |
85aaf69f | 744 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
745 | pub fn into_bytes(self) -> Vec<u8> { self.bytes } |
746 | ||
d9579d0f | 747 | /// Access the underlying UTF8-error that was the cause of this error. |
85aaf69f | 748 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
749 | pub fn utf8_error(&self) -> Utf8Error { self.error } |
750 | } | |
751 | ||
85aaf69f SL |
752 | #[stable(feature = "rust1", since = "1.0.0")] |
753 | impl fmt::Display for FromUtf8Error { | |
1a4d82fc | 754 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
85aaf69f | 755 | fmt::Display::fmt(&self.error, f) |
1a4d82fc JJ |
756 | } |
757 | } | |
758 | ||
85aaf69f SL |
759 | #[stable(feature = "rust1", since = "1.0.0")] |
760 | impl fmt::Display for FromUtf16Error { | |
1a4d82fc | 761 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
85aaf69f | 762 | fmt::Display::fmt("invalid utf-16: lone surrogate found", f) |
1a4d82fc JJ |
763 | } |
764 | } | |
765 | ||
85aaf69f | 766 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 767 | impl FromIterator<char> for String { |
85aaf69f | 768 | fn from_iter<I: IntoIterator<Item=char>>(iter: I) -> String { |
1a4d82fc | 769 | let mut buf = String::new(); |
85aaf69f | 770 | buf.extend(iter); |
1a4d82fc JJ |
771 | buf |
772 | } | |
773 | } | |
774 | ||
85aaf69f | 775 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 776 | impl<'a> FromIterator<&'a str> for String { |
85aaf69f | 777 | fn from_iter<I: IntoIterator<Item=&'a str>>(iter: I) -> String { |
1a4d82fc | 778 | let mut buf = String::new(); |
85aaf69f | 779 | buf.extend(iter); |
1a4d82fc JJ |
780 | buf |
781 | } | |
782 | } | |
783 | ||
bd371182 | 784 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 785 | impl Extend<char> for String { |
85aaf69f SL |
786 | fn extend<I: IntoIterator<Item=char>>(&mut self, iterable: I) { |
787 | let iterator = iterable.into_iter(); | |
1a4d82fc JJ |
788 | let (lower_bound, _) = iterator.size_hint(); |
789 | self.reserve(lower_bound); | |
790 | for ch in iterator { | |
791 | self.push(ch) | |
792 | } | |
793 | } | |
794 | } | |
795 | ||
62682a34 SL |
796 | #[stable(feature = "extend_ref", since = "1.2.0")] |
797 | impl<'a> Extend<&'a char> for String { | |
798 | fn extend<I: IntoIterator<Item=&'a char>>(&mut self, iter: I) { | |
799 | self.extend(iter.into_iter().cloned()); | |
800 | } | |
801 | } | |
802 | ||
bd371182 | 803 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 804 | impl<'a> Extend<&'a str> for String { |
85aaf69f SL |
805 | fn extend<I: IntoIterator<Item=&'a str>>(&mut self, iterable: I) { |
806 | let iterator = iterable.into_iter(); | |
1a4d82fc JJ |
807 | // A guess that at least one byte per iterator element will be needed. |
808 | let (lower_bound, _) = iterator.size_hint(); | |
809 | self.reserve(lower_bound); | |
810 | for s in iterator { | |
811 | self.push_str(s) | |
812 | } | |
813 | } | |
814 | } | |
815 | ||
c34b1796 AL |
816 | /// A convenience impl that delegates to the impl for `&str` |
817 | impl<'a, 'b> Pattern<'a> for &'b String { | |
818 | type Searcher = <&'b str as Pattern<'a>>::Searcher; | |
819 | ||
820 | fn into_searcher(self, haystack: &'a str) -> <&'b str as Pattern<'a>>::Searcher { | |
821 | self[..].into_searcher(haystack) | |
822 | } | |
823 | ||
824 | #[inline] | |
825 | fn is_contained_in(self, haystack: &'a str) -> bool { | |
826 | self[..].is_contained_in(haystack) | |
827 | } | |
828 | ||
829 | #[inline] | |
830 | fn is_prefix_of(self, haystack: &'a str) -> bool { | |
831 | self[..].is_prefix_of(haystack) | |
832 | } | |
833 | } | |
834 | ||
85aaf69f | 835 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
836 | impl PartialEq for String { |
837 | #[inline] | |
9346a6ac | 838 | fn eq(&self, other: &String) -> bool { PartialEq::eq(&self[..], &other[..]) } |
1a4d82fc | 839 | #[inline] |
9346a6ac | 840 | fn ne(&self, other: &String) -> bool { PartialEq::ne(&self[..], &other[..]) } |
1a4d82fc JJ |
841 | } |
842 | ||
843 | macro_rules! impl_eq { | |
844 | ($lhs:ty, $rhs: ty) => { | |
85aaf69f | 845 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
846 | impl<'a> PartialEq<$rhs> for $lhs { |
847 | #[inline] | |
9346a6ac | 848 | fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&self[..], &other[..]) } |
1a4d82fc | 849 | #[inline] |
9346a6ac | 850 | fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&self[..], &other[..]) } |
1a4d82fc JJ |
851 | } |
852 | ||
85aaf69f | 853 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
854 | impl<'a> PartialEq<$lhs> for $rhs { |
855 | #[inline] | |
9346a6ac | 856 | fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&self[..], &other[..]) } |
1a4d82fc | 857 | #[inline] |
9346a6ac | 858 | fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&self[..], &other[..]) } |
1a4d82fc JJ |
859 | } |
860 | ||
861 | } | |
862 | } | |
863 | ||
9346a6ac | 864 | impl_eq! { String, str } |
1a4d82fc | 865 | impl_eq! { String, &'a str } |
9346a6ac | 866 | impl_eq! { Cow<'a, str>, str } |
85aaf69f | 867 | impl_eq! { Cow<'a, str>, String } |
1a4d82fc | 868 | |
85aaf69f SL |
869 | #[stable(feature = "rust1", since = "1.0.0")] |
870 | impl<'a, 'b> PartialEq<&'b str> for Cow<'a, str> { | |
1a4d82fc | 871 | #[inline] |
9346a6ac | 872 | fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&self[..], &other[..]) } |
1a4d82fc | 873 | #[inline] |
9346a6ac | 874 | fn ne(&self, other: &&'b str) -> bool { PartialEq::ne(&self[..], &other[..]) } |
1a4d82fc JJ |
875 | } |
876 | ||
85aaf69f SL |
877 | #[stable(feature = "rust1", since = "1.0.0")] |
878 | impl<'a, 'b> PartialEq<Cow<'a, str>> for &'b str { | |
1a4d82fc | 879 | #[inline] |
9346a6ac | 880 | fn eq(&self, other: &Cow<'a, str>) -> bool { PartialEq::eq(&self[..], &other[..]) } |
1a4d82fc | 881 | #[inline] |
9346a6ac | 882 | fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&self[..], &other[..]) } |
1a4d82fc JJ |
883 | } |
884 | ||
85aaf69f | 885 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 886 | impl Default for String { |
85aaf69f SL |
887 | #[inline] |
888 | #[stable(feature = "rust1", since = "1.0.0")] | |
1a4d82fc JJ |
889 | fn default() -> String { |
890 | String::new() | |
891 | } | |
892 | } | |
893 | ||
85aaf69f SL |
894 | #[stable(feature = "rust1", since = "1.0.0")] |
895 | impl fmt::Display for String { | |
896 | #[inline] | |
1a4d82fc | 897 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
85aaf69f | 898 | fmt::Display::fmt(&**self, f) |
1a4d82fc JJ |
899 | } |
900 | } | |
901 | ||
85aaf69f SL |
902 | #[stable(feature = "rust1", since = "1.0.0")] |
903 | impl fmt::Debug for String { | |
904 | #[inline] | |
1a4d82fc | 905 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
85aaf69f | 906 | fmt::Debug::fmt(&**self, f) |
1a4d82fc JJ |
907 | } |
908 | } | |
909 | ||
85aaf69f | 910 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 911 | impl hash::Hash for String { |
1a4d82fc | 912 | #[inline] |
85aaf69f | 913 | fn hash<H: hash::Hasher>(&self, hasher: &mut H) { |
1a4d82fc JJ |
914 | (**self).hash(hasher) |
915 | } | |
916 | } | |
917 | ||
bd371182 | 918 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
919 | impl<'a> Add<&'a str> for String { |
920 | type Output = String; | |
921 | ||
85aaf69f | 922 | #[inline] |
1a4d82fc JJ |
923 | fn add(mut self, other: &str) -> String { |
924 | self.push_str(other); | |
925 | self | |
926 | } | |
927 | } | |
928 | ||
85aaf69f SL |
929 | #[stable(feature = "rust1", since = "1.0.0")] |
930 | impl ops::Index<ops::Range<usize>> for String { | |
1a4d82fc | 931 | type Output = str; |
c34b1796 | 932 | |
1a4d82fc | 933 | #[inline] |
c34b1796 AL |
934 | fn index(&self, index: ops::Range<usize>) -> &str { |
935 | &self[..][index] | |
1a4d82fc JJ |
936 | } |
937 | } | |
85aaf69f SL |
938 | #[stable(feature = "rust1", since = "1.0.0")] |
939 | impl ops::Index<ops::RangeTo<usize>> for String { | |
1a4d82fc | 940 | type Output = str; |
c34b1796 | 941 | |
1a4d82fc | 942 | #[inline] |
c34b1796 AL |
943 | fn index(&self, index: ops::RangeTo<usize>) -> &str { |
944 | &self[..][index] | |
1a4d82fc JJ |
945 | } |
946 | } | |
85aaf69f SL |
947 | #[stable(feature = "rust1", since = "1.0.0")] |
948 | impl ops::Index<ops::RangeFrom<usize>> for String { | |
1a4d82fc | 949 | type Output = str; |
c34b1796 | 950 | |
1a4d82fc | 951 | #[inline] |
c34b1796 AL |
952 | fn index(&self, index: ops::RangeFrom<usize>) -> &str { |
953 | &self[..][index] | |
1a4d82fc JJ |
954 | } |
955 | } | |
85aaf69f SL |
956 | #[stable(feature = "rust1", since = "1.0.0")] |
957 | impl ops::Index<ops::RangeFull> for String { | |
1a4d82fc | 958 | type Output = str; |
c34b1796 | 959 | |
1a4d82fc | 960 | #[inline] |
c34b1796 | 961 | fn index(&self, _index: ops::RangeFull) -> &str { |
85aaf69f | 962 | unsafe { mem::transmute(&*self.vec) } |
1a4d82fc JJ |
963 | } |
964 | } | |
965 | ||
85aaf69f | 966 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
967 | impl ops::Deref for String { |
968 | type Target = str; | |
969 | ||
85aaf69f SL |
970 | #[inline] |
971 | fn deref(&self) -> &str { | |
972 | unsafe { mem::transmute(&self.vec[..]) } | |
1a4d82fc JJ |
973 | } |
974 | } | |
975 | ||
976 | /// Wrapper type providing a `&String` reference via `Deref`. | |
85aaf69f | 977 | #[unstable(feature = "collections")] |
62682a34 SL |
978 | #[deprecated(since = "1.2.0", |
979 | reason = "replaced with deref coercions or Borrow")] | |
980 | #[allow(deprecated)] | |
1a4d82fc JJ |
981 | pub struct DerefString<'a> { |
982 | x: DerefVec<'a, u8> | |
983 | } | |
984 | ||
62682a34 | 985 | #[allow(deprecated)] |
1a4d82fc JJ |
986 | impl<'a> Deref for DerefString<'a> { |
987 | type Target = String; | |
988 | ||
85aaf69f | 989 | #[inline] |
1a4d82fc JJ |
990 | fn deref<'b>(&'b self) -> &'b String { |
991 | unsafe { mem::transmute(&*self.x) } | |
992 | } | |
993 | } | |
994 | ||
9346a6ac | 995 | /// Converts a string slice to a wrapper type providing a `&String` reference. |
1a4d82fc JJ |
996 | /// |
997 | /// # Examples | |
998 | /// | |
999 | /// ``` | |
c34b1796 | 1000 | /// # #![feature(collections)] |
1a4d82fc JJ |
1001 | /// use std::string::as_string; |
1002 | /// | |
bd371182 AL |
1003 | /// // Let's pretend we have a function that requires `&String` |
1004 | /// fn string_consumer(s: &String) { | |
1005 | /// assert_eq!(s, "foo"); | |
1a4d82fc JJ |
1006 | /// } |
1007 | /// | |
bd371182 AL |
1008 | /// // Provide a `&String` from a `&str` without allocating |
1009 | /// string_consumer(&as_string("foo")); | |
1a4d82fc | 1010 | /// ``` |
85aaf69f | 1011 | #[unstable(feature = "collections")] |
62682a34 SL |
1012 | #[deprecated(since = "1.2.0", |
1013 | reason = "replaced with deref coercions or Borrow")] | |
1014 | #[allow(deprecated)] | |
1a4d82fc JJ |
1015 | pub fn as_string<'a>(x: &'a str) -> DerefString<'a> { |
1016 | DerefString { x: as_vec(x.as_bytes()) } | |
1017 | } | |
1018 | ||
62682a34 | 1019 | /// Error returned from `String::from` |
bd371182 AL |
1020 | #[unstable(feature = "str_parse_error", reason = "may want to be replaced with \ |
1021 | Void if it ever exists")] | |
1022 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | |
1023 | pub struct ParseError(()); | |
1024 | ||
1025 | #[stable(feature = "rust1", since = "1.0.0")] | |
1a4d82fc | 1026 | impl FromStr for String { |
bd371182 | 1027 | type Err = ParseError; |
1a4d82fc | 1028 | #[inline] |
bd371182 | 1029 | fn from_str(s: &str) -> Result<String, ParseError> { |
62682a34 | 1030 | Ok(String::from(s)) |
1a4d82fc JJ |
1031 | } |
1032 | } | |
1033 | ||
1034 | /// A generic trait for converting a value to a string | |
85aaf69f | 1035 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1036 | pub trait ToString { |
1037 | /// Converts the value of `self` to an owned string | |
85aaf69f | 1038 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1039 | fn to_string(&self) -> String; |
1040 | } | |
1041 | ||
85aaf69f SL |
1042 | #[stable(feature = "rust1", since = "1.0.0")] |
1043 | impl<T: fmt::Display + ?Sized> ToString for T { | |
1044 | #[inline] | |
1a4d82fc | 1045 | fn to_string(&self) -> String { |
85aaf69f | 1046 | use core::fmt::Write; |
1a4d82fc JJ |
1047 | let mut buf = String::new(); |
1048 | let _ = buf.write_fmt(format_args!("{}", self)); | |
1049 | buf.shrink_to_fit(); | |
1050 | buf | |
1051 | } | |
1052 | } | |
1053 | ||
85aaf69f | 1054 | #[stable(feature = "rust1", since = "1.0.0")] |
c34b1796 | 1055 | impl AsRef<str> for String { |
d9579d0f | 1056 | #[inline] |
c34b1796 AL |
1057 | fn as_ref(&self) -> &str { |
1058 | self | |
1059 | } | |
1060 | } | |
1061 | ||
bd371182 AL |
1062 | #[stable(feature = "rust1", since = "1.0.0")] |
1063 | impl AsRef<[u8]> for String { | |
1064 | #[inline] | |
1065 | fn as_ref(&self) -> &[u8] { | |
1066 | self.as_bytes() | |
1067 | } | |
1068 | } | |
1069 | ||
c34b1796 AL |
1070 | #[stable(feature = "rust1", since = "1.0.0")] |
1071 | impl<'a> From<&'a str> for String { | |
d9579d0f | 1072 | #[cfg(not(test))] |
c34b1796 AL |
1073 | #[inline] |
1074 | fn from(s: &'a str) -> String { | |
d9579d0f AL |
1075 | String { vec: <[_]>::to_vec(s.as_bytes()) } |
1076 | } | |
1077 | ||
1078 | // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is | |
1079 | // required for this method definition, is not available. Since we don't | |
1080 | // require this method for testing purposes, I'll just stub it | |
1081 | // NB see the slice::hack module in slice.rs for more information | |
1082 | #[inline] | |
1083 | #[cfg(test)] | |
1084 | fn from(_: &str) -> String { | |
1085 | panic!("not available with cfg(test)"); | |
c34b1796 AL |
1086 | } |
1087 | } | |
1088 | ||
1089 | #[stable(feature = "rust1", since = "1.0.0")] | |
1090 | impl<'a> From<&'a str> for Cow<'a, str> { | |
1091 | #[inline] | |
1092 | fn from(s: &'a str) -> Cow<'a, str> { | |
1093 | Cow::Borrowed(s) | |
1094 | } | |
1095 | } | |
1096 | ||
1097 | #[stable(feature = "rust1", since = "1.0.0")] | |
1098 | impl<'a> From<String> for Cow<'a, str> { | |
1099 | #[inline] | |
1100 | fn from(s: String) -> Cow<'a, str> { | |
1101 | Cow::Owned(s) | |
1102 | } | |
1103 | } | |
1104 | ||
1105 | #[stable(feature = "rust1", since = "1.0.0")] | |
1106 | impl Into<Vec<u8>> for String { | |
1107 | fn into(self) -> Vec<u8> { | |
1108 | self.into_bytes() | |
1109 | } | |
1110 | } | |
1111 | ||
1112 | #[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")] | |
85aaf69f SL |
1113 | impl IntoCow<'static, str> for String { |
1114 | #[inline] | |
1115 | fn into_cow(self) -> Cow<'static, str> { | |
1a4d82fc JJ |
1116 | Cow::Owned(self) |
1117 | } | |
1118 | } | |
1119 | ||
c34b1796 | 1120 | #[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")] |
85aaf69f SL |
1121 | impl<'a> IntoCow<'a, str> for &'a str { |
1122 | #[inline] | |
1123 | fn into_cow(self) -> Cow<'a, str> { | |
1a4d82fc JJ |
1124 | Cow::Borrowed(self) |
1125 | } | |
1126 | } | |
1127 | ||
85aaf69f SL |
1128 | #[stable(feature = "rust1", since = "1.0.0")] |
1129 | impl fmt::Write for String { | |
1130 | #[inline] | |
1a4d82fc JJ |
1131 | fn write_str(&mut self, s: &str) -> fmt::Result { |
1132 | self.push_str(s); | |
1133 | Ok(()) | |
1134 | } | |
d9579d0f AL |
1135 | |
1136 | #[inline] | |
1137 | fn write_char(&mut self, c: char) -> fmt::Result { | |
1138 | self.push(c); | |
1139 | Ok(()) | |
1140 | } | |
1141 | } | |
1142 | ||
1143 | /// A draining iterator for `String`. | |
62682a34 | 1144 | #[unstable(feature = "drain", reason = "recently added")] |
d9579d0f AL |
1145 | pub struct Drain<'a> { |
1146 | /// Will be used as &'a mut String in the destructor | |
1147 | string: *mut String, | |
1148 | /// Start of part to remove | |
1149 | start: usize, | |
1150 | /// End of part to remove | |
1151 | end: usize, | |
1152 | /// Current remaining range to remove | |
1153 | iter: Chars<'a>, | |
1154 | } | |
1155 | ||
1156 | unsafe impl<'a> Sync for Drain<'a> {} | |
1157 | unsafe impl<'a> Send for Drain<'a> {} | |
1158 | ||
62682a34 | 1159 | #[unstable(feature = "drain", reason = "recently added")] |
d9579d0f AL |
1160 | impl<'a> Drop for Drain<'a> { |
1161 | fn drop(&mut self) { | |
1162 | unsafe { | |
1163 | // Use Vec::drain. "Reaffirm" the bounds checks to avoid | |
1164 | // panic code being inserted again. | |
1165 | let self_vec = (*self.string).as_mut_vec(); | |
1166 | if self.start <= self.end && self.end <= self_vec.len() { | |
1167 | self_vec.drain(self.start..self.end); | |
1168 | } | |
1169 | } | |
1170 | } | |
1171 | } | |
1172 | ||
62682a34 | 1173 | #[unstable(feature = "drain", reason = "recently added")] |
d9579d0f AL |
1174 | impl<'a> Iterator for Drain<'a> { |
1175 | type Item = char; | |
1176 | ||
1177 | #[inline] | |
1178 | fn next(&mut self) -> Option<char> { | |
1179 | self.iter.next() | |
1180 | } | |
1181 | ||
1182 | fn size_hint(&self) -> (usize, Option<usize>) { | |
1183 | self.iter.size_hint() | |
1184 | } | |
1185 | } | |
1186 | ||
62682a34 | 1187 | #[unstable(feature = "drain", reason = "recently added")] |
d9579d0f AL |
1188 | impl<'a> DoubleEndedIterator for Drain<'a> { |
1189 | #[inline] | |
1190 | fn next_back(&mut self) -> Option<char> { | |
1191 | self.iter.next_back() | |
1192 | } | |
1a4d82fc | 1193 | } |