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