]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys_common/wtf8.rs
Deprecate the AsciiExt trait in favor of inherent methods
[rust.git] / src / libstd / sys_common / wtf8.rs
1 // Copyright 2015 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.
10
11 //! Implementation of [the WTF-8 encoding](https://simonsapin.github.io/wtf-8/).
12 //!
13 //! This library uses Rust’s type system to maintain
14 //! [well-formedness](https://simonsapin.github.io/wtf-8/#well-formed),
15 //! like the `String` and `&str` types do for UTF-8.
16 //!
17 //! Since [WTF-8 must not be used
18 //! for interchange](https://simonsapin.github.io/wtf-8/#intended-audience),
19 //! this library deliberately does not provide access to the underlying bytes
20 //! of WTF-8 strings,
21 //! nor can it decode WTF-8 from arbitrary bytes.
22 //! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points.
23
24 // this module is imported from @SimonSapin's repo and has tons of dead code on
25 // unix (it's mostly used on windows), so don't worry about dead code here.
26 #![allow(dead_code)]
27
28 use core::str::next_code_point;
29
30 use borrow::Cow;
31 use char;
32 use fmt;
33 use hash::{Hash, Hasher};
34 use iter::FromIterator;
35 use mem;
36 use ops;
37 use rc::Rc;
38 use slice;
39 use str;
40 use sync::Arc;
41 use sys_common::AsInner;
42
43 const UTF8_REPLACEMENT_CHARACTER: &'static str = "\u{FFFD}";
44
45 /// A Unicode code point: from U+0000 to U+10FFFF.
46 ///
47 /// Compare with the `char` type,
48 /// which represents a Unicode scalar value:
49 /// a code point that is not a surrogate (U+D800 to U+DFFF).
50 #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
51 pub struct CodePoint {
52     value: u32
53 }
54
55 /// Format the code point as `U+` followed by four to six hexadecimal digits.
56 /// Example: `U+1F4A9`
57 impl fmt::Debug for CodePoint {
58     #[inline]
59     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
60         write!(formatter, "U+{:04X}", self.value)
61     }
62 }
63
64 impl CodePoint {
65     /// Unsafely creates a new `CodePoint` without checking the value.
66     ///
67     /// Only use when `value` is known to be less than or equal to 0x10FFFF.
68     #[inline]
69     pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint {
70         CodePoint { value: value }
71     }
72
73     /// Creates a new `CodePoint` if the value is a valid code point.
74     ///
75     /// Returns `None` if `value` is above 0x10FFFF.
76     #[inline]
77     pub fn from_u32(value: u32) -> Option<CodePoint> {
78         match value {
79             0 ... 0x10FFFF => Some(CodePoint { value: value }),
80             _ => None
81         }
82     }
83
84     /// Creates a new `CodePoint` from a `char`.
85     ///
86     /// Since all Unicode scalar values are code points, this always succeeds.
87     #[inline]
88     pub fn from_char(value: char) -> CodePoint {
89         CodePoint { value: value as u32 }
90     }
91
92     /// Returns the numeric value of the code point.
93     #[inline]
94     pub fn to_u32(&self) -> u32 {
95         self.value
96     }
97
98     /// Optionally returns a Unicode scalar value for the code point.
99     ///
100     /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF).
101     #[inline]
102     pub fn to_char(&self) -> Option<char> {
103         match self.value {
104             0xD800 ... 0xDFFF => None,
105             _ => Some(unsafe { char::from_u32_unchecked(self.value) })
106         }
107     }
108
109     /// Returns a Unicode scalar value for the code point.
110     ///
111     /// Returns `'\u{FFFD}'` (the replacement character “�”)
112     /// if the code point is a surrogate (from U+D800 to U+DFFF).
113     #[inline]
114     pub fn to_char_lossy(&self) -> char {
115         self.to_char().unwrap_or('\u{FFFD}')
116     }
117 }
118
119 /// An owned, growable string of well-formed WTF-8 data.
120 ///
121 /// Similar to `String`, but can additionally contain surrogate code points
122 /// if they’re not in a surrogate pair.
123 #[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
124 pub struct Wtf8Buf {
125     bytes: Vec<u8>
126 }
127
128 impl ops::Deref for Wtf8Buf {
129     type Target = Wtf8;
130
131     fn deref(&self) -> &Wtf8 {
132         self.as_slice()
133     }
134 }
135
136 impl ops::DerefMut for Wtf8Buf {
137     fn deref_mut(&mut self) -> &mut Wtf8 {
138         self.as_mut_slice()
139     }
140 }
141
142 /// Format the string with double quotes,
143 /// and surrogates as `\u` followed by four hexadecimal digits.
144 /// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800]
145 impl fmt::Debug for Wtf8Buf {
146     #[inline]
147     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
148         fmt::Debug::fmt(&**self, formatter)
149     }
150 }
151
152 impl Wtf8Buf {
153     /// Creates a new, empty WTF-8 string.
154     #[inline]
155     pub fn new() -> Wtf8Buf {
156         Wtf8Buf { bytes: Vec::new() }
157     }
158
159     /// Creates a new, empty WTF-8 string with pre-allocated capacity for `n` bytes.
160     #[inline]
161     pub fn with_capacity(n: usize) -> Wtf8Buf {
162         Wtf8Buf { bytes: Vec::with_capacity(n) }
163     }
164
165     /// Creates a WTF-8 string from a UTF-8 `String`.
166     ///
167     /// This takes ownership of the `String` and does not copy.
168     ///
169     /// Since WTF-8 is a superset of UTF-8, this always succeeds.
170     #[inline]
171     pub fn from_string(string: String) -> Wtf8Buf {
172         Wtf8Buf { bytes: string.into_bytes() }
173     }
174
175     /// Creates a WTF-8 string from a UTF-8 `&str` slice.
176     ///
177     /// This copies the content of the slice.
178     ///
179     /// Since WTF-8 is a superset of UTF-8, this always succeeds.
180     #[inline]
181     pub fn from_str(str: &str) -> Wtf8Buf {
182         Wtf8Buf { bytes: <[_]>::to_vec(str.as_bytes()) }
183     }
184
185     pub fn clear(&mut self) {
186         self.bytes.clear()
187     }
188
189     /// Creates a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units.
190     ///
191     /// This is lossless: calling `.encode_wide()` on the resulting string
192     /// will always return the original code units.
193     pub fn from_wide(v: &[u16]) -> Wtf8Buf {
194         let mut string = Wtf8Buf::with_capacity(v.len());
195         for item in char::decode_utf16(v.iter().cloned()) {
196             match item {
197                 Ok(ch) => string.push_char(ch),
198                 Err(surrogate) => {
199                     let surrogate = surrogate.unpaired_surrogate();
200                     // Surrogates are known to be in the code point range.
201                     let code_point = unsafe {
202                         CodePoint::from_u32_unchecked(surrogate as u32)
203                     };
204                     // Skip the WTF-8 concatenation check,
205                     // surrogate pairs are already decoded by decode_utf16
206                     string.push_code_point_unchecked(code_point)
207                 }
208             }
209         }
210         string
211     }
212
213     /// Copied from String::push
214     /// This does **not** include the WTF-8 concatenation check.
215     fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
216         let c = unsafe {
217             char::from_u32_unchecked(code_point.value)
218         };
219         let mut bytes = [0; 4];
220         let bytes = c.encode_utf8(&mut bytes).as_bytes();
221         self.bytes.extend_from_slice(bytes)
222     }
223
224     #[inline]
225     pub fn as_slice(&self) -> &Wtf8 {
226         unsafe { Wtf8::from_bytes_unchecked(&self.bytes) }
227     }
228
229     #[inline]
230     pub fn as_mut_slice(&mut self) -> &mut Wtf8 {
231         unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) }
232     }
233
234     /// Reserves capacity for at least `additional` more bytes to be inserted
235     /// in the given `Wtf8Buf`.
236     /// The collection may reserve more space to avoid frequent reallocations.
237     ///
238     /// # Panics
239     ///
240     /// Panics if the new capacity overflows `usize`.
241     #[inline]
242     pub fn reserve(&mut self, additional: usize) {
243         self.bytes.reserve(additional)
244     }
245
246     #[inline]
247     pub fn reserve_exact(&mut self, additional: usize) {
248         self.bytes.reserve_exact(additional)
249     }
250
251     #[inline]
252     pub fn shrink_to_fit(&mut self) {
253         self.bytes.shrink_to_fit()
254     }
255
256     /// Returns the number of bytes that this string buffer can hold without reallocating.
257     #[inline]
258     pub fn capacity(&self) -> usize {
259         self.bytes.capacity()
260     }
261
262     /// Append a UTF-8 slice at the end of the string.
263     #[inline]
264     pub fn push_str(&mut self, other: &str) {
265         self.bytes.extend_from_slice(other.as_bytes())
266     }
267
268     /// Append a WTF-8 slice at the end of the string.
269     ///
270     /// This replaces newly paired surrogates at the boundary
271     /// with a supplementary code point,
272     /// like concatenating ill-formed UTF-16 strings effectively would.
273     #[inline]
274     pub fn push_wtf8(&mut self, other: &Wtf8) {
275         match ((&*self).final_lead_surrogate(), other.initial_trail_surrogate()) {
276             // Replace newly paired surrogates by a supplementary code point.
277             (Some(lead), Some(trail)) => {
278                 let len_without_lead_surrogate = self.len() - 3;
279                 self.bytes.truncate(len_without_lead_surrogate);
280                 let other_without_trail_surrogate = &other.bytes[3..];
281                 // 4 bytes for the supplementary code point
282                 self.bytes.reserve(4 + other_without_trail_surrogate.len());
283                 self.push_char(decode_surrogate_pair(lead, trail));
284                 self.bytes.extend_from_slice(other_without_trail_surrogate);
285             }
286             _ => self.bytes.extend_from_slice(&other.bytes)
287         }
288     }
289
290     /// Append a Unicode scalar value at the end of the string.
291     #[inline]
292     pub fn push_char(&mut self, c: char) {
293         self.push_code_point_unchecked(CodePoint::from_char(c))
294     }
295
296     /// Append a code point at the end of the string.
297     ///
298     /// This replaces newly paired surrogates at the boundary
299     /// with a supplementary code point,
300     /// like concatenating ill-formed UTF-16 strings effectively would.
301     #[inline]
302     pub fn push(&mut self, code_point: CodePoint) {
303         if let trail @ 0xDC00...0xDFFF = code_point.to_u32() {
304             if let Some(lead) = (&*self).final_lead_surrogate() {
305                 let len_without_lead_surrogate = self.len() - 3;
306                 self.bytes.truncate(len_without_lead_surrogate);
307                 self.push_char(decode_surrogate_pair(lead, trail as u16));
308                 return
309             }
310         }
311
312         // No newly paired surrogates at the boundary.
313         self.push_code_point_unchecked(code_point)
314     }
315
316     /// Shortens a string to the specified length.
317     ///
318     /// # Panics
319     ///
320     /// Panics if `new_len` > current length,
321     /// or if `new_len` is not a code point boundary.
322     #[inline]
323     pub fn truncate(&mut self, new_len: usize) {
324         assert!(is_code_point_boundary(self, new_len));
325         self.bytes.truncate(new_len)
326     }
327
328     /// Consumes the WTF-8 string and tries to convert it to UTF-8.
329     ///
330     /// This does not copy the data.
331     ///
332     /// If the contents are not well-formed UTF-8
333     /// (that is, if the string contains surrogates),
334     /// the original WTF-8 string is returned instead.
335     pub fn into_string(self) -> Result<String, Wtf8Buf> {
336         match self.next_surrogate(0) {
337             None => Ok(unsafe { String::from_utf8_unchecked(self.bytes) }),
338             Some(_) => Err(self),
339         }
340     }
341
342     /// Consumes the WTF-8 string and converts it lossily to UTF-8.
343     ///
344     /// This does not copy the data (but may overwrite parts of it in place).
345     ///
346     /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”)
347     pub fn into_string_lossy(mut self) -> String {
348         let mut pos = 0;
349         loop {
350             match self.next_surrogate(pos) {
351                 Some((surrogate_pos, _)) => {
352                     pos = surrogate_pos + 3;
353                     self.bytes[surrogate_pos..pos]
354                         .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
355                 },
356                 None => return unsafe { String::from_utf8_unchecked(self.bytes) }
357             }
358         }
359     }
360
361     /// Converts this `Wtf8Buf` into a boxed `Wtf8`.
362     #[inline]
363     pub fn into_box(self) -> Box<Wtf8> {
364         unsafe { mem::transmute(self.bytes.into_boxed_slice()) }
365     }
366
367     /// Converts a `Box<Wtf8>` into a `Wtf8Buf`.
368     pub fn from_box(boxed: Box<Wtf8>) -> Wtf8Buf {
369         let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) };
370         Wtf8Buf { bytes: bytes.into_vec() }
371     }
372 }
373
374 /// Create a new WTF-8 string from an iterator of code points.
375 ///
376 /// This replaces surrogate code point pairs with supplementary code points,
377 /// like concatenating ill-formed UTF-16 strings effectively would.
378 impl FromIterator<CodePoint> for Wtf8Buf {
379     fn from_iter<T: IntoIterator<Item=CodePoint>>(iter: T) -> Wtf8Buf {
380         let mut string = Wtf8Buf::new();
381         string.extend(iter);
382         string
383     }
384 }
385
386 /// Append code points from an iterator to the string.
387 ///
388 /// This replaces surrogate code point pairs with supplementary code points,
389 /// like concatenating ill-formed UTF-16 strings effectively would.
390 impl Extend<CodePoint> for Wtf8Buf {
391     fn extend<T: IntoIterator<Item=CodePoint>>(&mut self, iter: T) {
392         let iterator = iter.into_iter();
393         let (low, _high) = iterator.size_hint();
394         // Lower bound of one byte per code point (ASCII only)
395         self.bytes.reserve(low);
396         for code_point in iterator {
397             self.push(code_point);
398         }
399     }
400 }
401
402 /// A borrowed slice of well-formed WTF-8 data.
403 ///
404 /// Similar to `&str`, but can additionally contain surrogate code points
405 /// if they’re not in a surrogate pair.
406 #[derive(Eq, Ord, PartialEq, PartialOrd)]
407 pub struct Wtf8 {
408     bytes: [u8]
409 }
410
411 impl AsInner<[u8]> for Wtf8 {
412     fn as_inner(&self) -> &[u8] { &self.bytes }
413 }
414
415 /// Format the slice with double quotes,
416 /// and surrogates as `\u` followed by four hexadecimal digits.
417 /// Example: `"a\u{D800}"` for a slice with code points [U+0061, U+D800]
418 impl fmt::Debug for Wtf8 {
419     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
420         fn write_str_escaped(f: &mut fmt::Formatter, s: &str) -> fmt::Result {
421             use fmt::Write;
422             for c in s.chars().flat_map(|c| c.escape_debug()) {
423                 f.write_char(c)?
424             }
425             Ok(())
426         }
427
428         formatter.write_str("\"")?;
429         let mut pos = 0;
430         while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
431             write_str_escaped(
432                 formatter,
433                 unsafe { str::from_utf8_unchecked(
434                     &self.bytes[pos .. surrogate_pos]
435                 )},
436             )?;
437             write!(formatter, "\\u{{{:x}}}", surrogate)?;
438             pos = surrogate_pos + 3;
439         }
440         write_str_escaped(
441             formatter,
442             unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) },
443         )?;
444         formatter.write_str("\"")
445     }
446 }
447
448 impl fmt::Display for Wtf8 {
449     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
450         let wtf8_bytes = &self.bytes;
451         let mut pos = 0;
452         loop {
453             match self.next_surrogate(pos) {
454                 Some((surrogate_pos, _)) => {
455                     formatter.write_str(unsafe {
456                         str::from_utf8_unchecked(&wtf8_bytes[pos .. surrogate_pos])
457                     })?;
458                     formatter.write_str(UTF8_REPLACEMENT_CHARACTER)?;
459                     pos = surrogate_pos + 3;
460                 },
461                 None => {
462                     let s = unsafe {
463                         str::from_utf8_unchecked(&wtf8_bytes[pos..])
464                     };
465                     if pos == 0 {
466                         return s.fmt(formatter)
467                     } else {
468                         return formatter.write_str(s)
469                     }
470                 }
471             }
472         }
473     }
474 }
475
476 impl Wtf8 {
477     /// Creates a WTF-8 slice from a UTF-8 `&str` slice.
478     ///
479     /// Since WTF-8 is a superset of UTF-8, this always succeeds.
480     #[inline]
481     pub fn from_str(value: &str) -> &Wtf8 {
482         unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) }
483     }
484
485     /// Creates a WTF-8 slice from a WTF-8 byte slice.
486     ///
487     /// Since the byte slice is not checked for valid WTF-8, this functions is
488     /// marked unsafe.
489     #[inline]
490     unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
491         mem::transmute(value)
492     }
493
494     /// Creates a mutable WTF-8 slice from a mutable WTF-8 byte slice.
495     ///
496     /// Since the byte slice is not checked for valid WTF-8, this functions is
497     /// marked unsafe.
498     #[inline]
499     unsafe fn from_mut_bytes_unchecked(value: &mut [u8]) -> &mut Wtf8 {
500         mem::transmute(value)
501     }
502
503     /// Returns the length, in WTF-8 bytes.
504     #[inline]
505     pub fn len(&self) -> usize {
506         self.bytes.len()
507     }
508
509     #[inline]
510     pub fn is_empty(&self) -> bool {
511         self.bytes.is_empty()
512     }
513
514     /// Returns the code point at `position` if it is in the ASCII range,
515     /// or `b'\xFF' otherwise.
516     ///
517     /// # Panics
518     ///
519     /// Panics if `position` is beyond the end of the string.
520     #[inline]
521     pub fn ascii_byte_at(&self, position: usize) -> u8 {
522         match self.bytes[position] {
523             ascii_byte @ 0x00 ... 0x7F => ascii_byte,
524             _ => 0xFF
525         }
526     }
527
528     /// Returns an iterator for the string’s code points.
529     #[inline]
530     pub fn code_points(&self) -> Wtf8CodePoints {
531         Wtf8CodePoints { bytes: self.bytes.iter() }
532     }
533
534     /// Tries to convert the string to UTF-8 and return a `&str` slice.
535     ///
536     /// Returns `None` if the string contains surrogates.
537     ///
538     /// This does not copy the data.
539     #[inline]
540     pub fn as_str(&self) -> Option<&str> {
541         // Well-formed WTF-8 is also well-formed UTF-8
542         // if and only if it contains no surrogate.
543         match self.next_surrogate(0) {
544             None => Some(unsafe { str::from_utf8_unchecked(&self.bytes) }),
545             Some(_) => None,
546         }
547     }
548
549     /// Lossily converts the string to UTF-8.
550     /// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8.
551     ///
552     /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”).
553     ///
554     /// This only copies the data if necessary (if it contains any surrogate).
555     pub fn to_string_lossy(&self) -> Cow<str> {
556         let surrogate_pos = match self.next_surrogate(0) {
557             None => return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }),
558             Some((pos, _)) => pos,
559         };
560         let wtf8_bytes = &self.bytes;
561         let mut utf8_bytes = Vec::with_capacity(self.len());
562         utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]);
563         utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
564         let mut pos = surrogate_pos + 3;
565         loop {
566             match self.next_surrogate(pos) {
567                 Some((surrogate_pos, _)) => {
568                     utf8_bytes.extend_from_slice(&wtf8_bytes[pos .. surrogate_pos]);
569                     utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
570                     pos = surrogate_pos + 3;
571                 },
572                 None => {
573                     utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]);
574                     return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) })
575                 }
576             }
577         }
578     }
579
580     /// Converts the WTF-8 string to potentially ill-formed UTF-16
581     /// and return an iterator of 16-bit code units.
582     ///
583     /// This is lossless:
584     /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units
585     /// would always return the original WTF-8 string.
586     #[inline]
587     pub fn encode_wide(&self) -> EncodeWide {
588         EncodeWide { code_points: self.code_points(), extra: 0 }
589     }
590
591     #[inline]
592     fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> {
593         let mut iter = self.bytes[pos..].iter();
594         loop {
595             let b = *iter.next()?;
596             if b < 0x80 {
597                 pos += 1;
598             } else if b < 0xE0 {
599                 iter.next();
600                 pos += 2;
601             } else if b == 0xED {
602                 match (iter.next(), iter.next()) {
603                     (Some(&b2), Some(&b3)) if b2 >= 0xA0 => {
604                         return Some((pos, decode_surrogate(b2, b3)))
605                     }
606                     _ => pos += 3
607                 }
608             } else if b < 0xF0 {
609                 iter.next();
610                 iter.next();
611                 pos += 3;
612             } else {
613                 iter.next();
614                 iter.next();
615                 iter.next();
616                 pos += 4;
617             }
618         }
619     }
620
621     #[inline]
622     fn final_lead_surrogate(&self) -> Option<u16> {
623         let len = self.len();
624         if len < 3 {
625             return None
626         }
627         match &self.bytes[(len - 3)..] {
628             &[0xED, b2 @ 0xA0...0xAF, b3] => Some(decode_surrogate(b2, b3)),
629             _ => None
630         }
631     }
632
633     #[inline]
634     fn initial_trail_surrogate(&self) -> Option<u16> {
635         let len = self.len();
636         if len < 3 {
637             return None
638         }
639         match &self.bytes[..3] {
640             &[0xED, b2 @ 0xB0...0xBF, b3] => Some(decode_surrogate(b2, b3)),
641             _ => None
642         }
643     }
644
645     /// Boxes this `Wtf8`.
646     #[inline]
647     pub fn into_box(&self) -> Box<Wtf8> {
648         let boxed: Box<[u8]> = self.bytes.into();
649         unsafe { mem::transmute(boxed) }
650     }
651
652     /// Creates a boxed, empty `Wtf8`.
653     pub fn empty_box() -> Box<Wtf8> {
654         let boxed: Box<[u8]> = Default::default();
655         unsafe { mem::transmute(boxed) }
656     }
657
658     #[inline]
659     pub fn into_arc(&self) -> Arc<Wtf8> {
660         let arc: Arc<[u8]> = Arc::from(&self.bytes);
661         unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) }
662     }
663
664     #[inline]
665     pub fn into_rc(&self) -> Rc<Wtf8> {
666         let rc: Rc<[u8]> = Rc::from(&self.bytes);
667         unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) }
668     }
669 }
670
671
672 /// Return a slice of the given string for the byte range [`begin`..`end`).
673 ///
674 /// # Panics
675 ///
676 /// Panics when `begin` and `end` do not point to code point boundaries,
677 /// or point beyond the end of the string.
678 impl ops::Index<ops::Range<usize>> for Wtf8 {
679     type Output = Wtf8;
680
681     #[inline]
682     fn index(&self, range: ops::Range<usize>) -> &Wtf8 {
683         // is_code_point_boundary checks that the index is in [0, .len()]
684         if range.start <= range.end &&
685            is_code_point_boundary(self, range.start) &&
686            is_code_point_boundary(self, range.end) {
687             unsafe { slice_unchecked(self, range.start, range.end) }
688         } else {
689             slice_error_fail(self, range.start, range.end)
690         }
691     }
692 }
693
694 /// Return a slice of the given string from byte `begin` to its end.
695 ///
696 /// # Panics
697 ///
698 /// Panics when `begin` is not at a code point boundary,
699 /// or is beyond the end of the string.
700 impl ops::Index<ops::RangeFrom<usize>> for Wtf8 {
701     type Output = Wtf8;
702
703     #[inline]
704     fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 {
705         // is_code_point_boundary checks that the index is in [0, .len()]
706         if is_code_point_boundary(self, range.start) {
707             unsafe { slice_unchecked(self, range.start, self.len()) }
708         } else {
709             slice_error_fail(self, range.start, self.len())
710         }
711     }
712 }
713
714 /// Return a slice of the given string from its beginning to byte `end`.
715 ///
716 /// # Panics
717 ///
718 /// Panics when `end` is not at a code point boundary,
719 /// or is beyond the end of the string.
720 impl ops::Index<ops::RangeTo<usize>> for Wtf8 {
721     type Output = Wtf8;
722
723     #[inline]
724     fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 {
725         // is_code_point_boundary checks that the index is in [0, .len()]
726         if is_code_point_boundary(self, range.end) {
727             unsafe { slice_unchecked(self, 0, range.end) }
728         } else {
729             slice_error_fail(self, 0, range.end)
730         }
731     }
732 }
733
734 impl ops::Index<ops::RangeFull> for Wtf8 {
735     type Output = Wtf8;
736
737     #[inline]
738     fn index(&self, _range: ops::RangeFull) -> &Wtf8 {
739         self
740     }
741 }
742
743 #[inline]
744 fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 {
745     // The first byte is assumed to be 0xED
746     0xD800 | (second_byte as u16 & 0x3F) << 6 | third_byte as u16 & 0x3F
747 }
748
749 #[inline]
750 fn decode_surrogate_pair(lead: u16, trail: u16) -> char {
751     let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32);
752     unsafe { char::from_u32_unchecked(code_point) }
753 }
754
755 /// Copied from core::str::StrPrelude::is_char_boundary
756 #[inline]
757 pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
758     if index == slice.len() { return true; }
759     match slice.bytes.get(index) {
760         None => false,
761         Some(&b) => b < 128 || b >= 192,
762     }
763 }
764
765 /// Copied from core::str::raw::slice_unchecked
766 #[inline]
767 pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
768     // memory layout of an &[u8] and &Wtf8 are the same
769     Wtf8::from_bytes_unchecked(slice::from_raw_parts(
770         s.bytes.as_ptr().offset(begin as isize),
771         end - begin
772     ))
773 }
774
775 /// Copied from core::str::raw::slice_error_fail
776 #[inline(never)]
777 pub fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! {
778     assert!(begin <= end);
779     panic!("index {} and/or {} in `{:?}` do not lie on character boundary",
780           begin, end, s);
781 }
782
783 /// Iterator for the code points of a WTF-8 string.
784 ///
785 /// Created with the method `.code_points()`.
786 #[derive(Clone)]
787 pub struct Wtf8CodePoints<'a> {
788     bytes: slice::Iter<'a, u8>
789 }
790
791 impl<'a> Iterator for Wtf8CodePoints<'a> {
792     type Item = CodePoint;
793
794     #[inline]
795     fn next(&mut self) -> Option<CodePoint> {
796         next_code_point(&mut self.bytes).map(|c| CodePoint { value: c })
797     }
798
799     #[inline]
800     fn size_hint(&self) -> (usize, Option<usize>) {
801         let len = self.bytes.len();
802         (len.saturating_add(3) / 4, Some(len))
803     }
804 }
805
806 /// Generates a wide character sequence for potentially ill-formed UTF-16.
807 #[stable(feature = "rust1", since = "1.0.0")]
808 #[derive(Clone)]
809 pub struct EncodeWide<'a> {
810     code_points: Wtf8CodePoints<'a>,
811     extra: u16
812 }
813
814 // Copied from libunicode/u_str.rs
815 #[stable(feature = "rust1", since = "1.0.0")]
816 impl<'a> Iterator for EncodeWide<'a> {
817     type Item = u16;
818
819     #[inline]
820     fn next(&mut self) -> Option<u16> {
821         if self.extra != 0 {
822             let tmp = self.extra;
823             self.extra = 0;
824             return Some(tmp);
825         }
826
827         let mut buf = [0; 2];
828         self.code_points.next().map(|code_point| {
829             let c = unsafe {
830                 char::from_u32_unchecked(code_point.value)
831             };
832             let n = c.encode_utf16(&mut buf).len();
833             if n == 2 {
834                 self.extra = buf[1];
835             }
836             buf[0]
837         })
838     }
839
840     #[inline]
841     fn size_hint(&self) -> (usize, Option<usize>) {
842         let (low, high) = self.code_points.size_hint();
843         // every code point gets either one u16 or two u16,
844         // so this iterator is between 1 or 2 times as
845         // long as the underlying iterator.
846         (low, high.and_then(|n| n.checked_mul(2)))
847     }
848 }
849
850 impl Hash for CodePoint {
851     #[inline]
852     fn hash<H: Hasher>(&self, state: &mut H) {
853         self.value.hash(state)
854     }
855 }
856
857 impl Hash for Wtf8Buf {
858     #[inline]
859     fn hash<H: Hasher>(&self, state: &mut H) {
860         state.write(&self.bytes);
861         0xfeu8.hash(state)
862     }
863 }
864
865 impl Hash for Wtf8 {
866     #[inline]
867     fn hash<H: Hasher>(&self, state: &mut H) {
868         state.write(&self.bytes);
869         0xfeu8.hash(state)
870     }
871 }
872
873 impl Wtf8 {
874     pub fn is_ascii(&self) -> bool {
875         self.bytes.is_ascii()
876     }
877     pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
878         Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
879     }
880     pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
881         Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
882     }
883     pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
884         self.bytes.eq_ignore_ascii_case(&other.bytes)
885     }
886
887     pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
888     pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
889 }
890
891 #[cfg(test)]
892 mod tests {
893     use borrow::Cow;
894     use super::*;
895
896     #[test]
897     fn code_point_from_u32() {
898         assert!(CodePoint::from_u32(0).is_some());
899         assert!(CodePoint::from_u32(0xD800).is_some());
900         assert!(CodePoint::from_u32(0x10FFFF).is_some());
901         assert!(CodePoint::from_u32(0x110000).is_none());
902     }
903
904     #[test]
905     fn code_point_to_u32() {
906         fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() }
907         assert_eq!(c(0).to_u32(), 0);
908         assert_eq!(c(0xD800).to_u32(), 0xD800);
909         assert_eq!(c(0x10FFFF).to_u32(), 0x10FFFF);
910     }
911
912     #[test]
913     fn code_point_from_char() {
914         assert_eq!(CodePoint::from_char('a').to_u32(), 0x61);
915         assert_eq!(CodePoint::from_char('💩').to_u32(), 0x1F4A9);
916     }
917
918     #[test]
919     fn code_point_to_string() {
920         assert_eq!(format!("{:?}", CodePoint::from_char('a')), "U+0061");
921         assert_eq!(format!("{:?}", CodePoint::from_char('💩')), "U+1F4A9");
922     }
923
924     #[test]
925     fn code_point_to_char() {
926         fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() }
927         assert_eq!(c(0x61).to_char(), Some('a'));
928         assert_eq!(c(0x1F4A9).to_char(), Some('💩'));
929         assert_eq!(c(0xD800).to_char(), None);
930     }
931
932     #[test]
933     fn code_point_to_char_lossy() {
934         fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() }
935         assert_eq!(c(0x61).to_char_lossy(), 'a');
936         assert_eq!(c(0x1F4A9).to_char_lossy(), '💩');
937         assert_eq!(c(0xD800).to_char_lossy(), '\u{FFFD}');
938     }
939
940     #[test]
941     fn wtf8buf_new() {
942         assert_eq!(Wtf8Buf::new().bytes, b"");
943     }
944
945     #[test]
946     fn wtf8buf_from_str() {
947         assert_eq!(Wtf8Buf::from_str("").bytes, b"");
948         assert_eq!(Wtf8Buf::from_str("aé 💩").bytes,
949                    b"a\xC3\xA9 \xF0\x9F\x92\xA9");
950     }
951
952     #[test]
953     fn wtf8buf_from_string() {
954         assert_eq!(Wtf8Buf::from_string(String::from("")).bytes, b"");
955         assert_eq!(Wtf8Buf::from_string(String::from("aé 💩")).bytes,
956                    b"a\xC3\xA9 \xF0\x9F\x92\xA9");
957     }
958
959     #[test]
960     fn wtf8buf_from_wide() {
961         assert_eq!(Wtf8Buf::from_wide(&[]).bytes, b"");
962         assert_eq!(Wtf8Buf::from_wide(
963                       &[0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]).bytes,
964                    b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9");
965     }
966
967     #[test]
968     fn wtf8buf_push_str() {
969         let mut string = Wtf8Buf::new();
970         assert_eq!(string.bytes, b"");
971         string.push_str("aé 💩");
972         assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
973     }
974
975     #[test]
976     fn wtf8buf_push_char() {
977         let mut string = Wtf8Buf::from_str("aé ");
978         assert_eq!(string.bytes, b"a\xC3\xA9 ");
979         string.push_char('💩');
980         assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
981     }
982
983     #[test]
984     fn wtf8buf_push() {
985         let mut string = Wtf8Buf::from_str("aé ");
986         assert_eq!(string.bytes, b"a\xC3\xA9 ");
987         string.push(CodePoint::from_char('💩'));
988         assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
989
990         fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() }
991
992         let mut string = Wtf8Buf::new();
993         string.push(c(0xD83D));  // lead
994         string.push(c(0xDCA9));  // trail
995         assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9");  // Magic!
996
997         let mut string = Wtf8Buf::new();
998         string.push(c(0xD83D));  // lead
999         string.push(c(0x20));  // not surrogate
1000         string.push(c(0xDCA9));  // trail
1001         assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
1002
1003         let mut string = Wtf8Buf::new();
1004         string.push(c(0xD800));  // lead
1005         string.push(c(0xDBFF));  // lead
1006         assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF");
1007
1008         let mut string = Wtf8Buf::new();
1009         string.push(c(0xD800));  // lead
1010         string.push(c(0xE000));  // not surrogate
1011         assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80");
1012
1013         let mut string = Wtf8Buf::new();
1014         string.push(c(0xD7FF));  // not surrogate
1015         string.push(c(0xDC00));  // trail
1016         assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80");
1017
1018         let mut string = Wtf8Buf::new();
1019         string.push(c(0x61));  // not surrogate, < 3 bytes
1020         string.push(c(0xDC00));  // trail
1021         assert_eq!(string.bytes, b"\x61\xED\xB0\x80");
1022
1023         let mut string = Wtf8Buf::new();
1024         string.push(c(0xDC00));  // trail
1025         assert_eq!(string.bytes, b"\xED\xB0\x80");
1026     }
1027
1028     #[test]
1029     fn wtf8buf_push_wtf8() {
1030         let mut string = Wtf8Buf::from_str("aé");
1031         assert_eq!(string.bytes, b"a\xC3\xA9");
1032         string.push_wtf8(Wtf8::from_str(" 💩"));
1033         assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
1034
1035         fn w(v: &[u8]) -> &Wtf8 { unsafe { Wtf8::from_bytes_unchecked(v) } }
1036
1037         let mut string = Wtf8Buf::new();
1038         string.push_wtf8(w(b"\xED\xA0\xBD"));  // lead
1039         string.push_wtf8(w(b"\xED\xB2\xA9"));  // trail
1040         assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9");  // Magic!
1041
1042         let mut string = Wtf8Buf::new();
1043         string.push_wtf8(w(b"\xED\xA0\xBD"));  // lead
1044         string.push_wtf8(w(b" "));  // not surrogate
1045         string.push_wtf8(w(b"\xED\xB2\xA9"));  // trail
1046         assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
1047
1048         let mut string = Wtf8Buf::new();
1049         string.push_wtf8(w(b"\xED\xA0\x80"));  // lead
1050         string.push_wtf8(w(b"\xED\xAF\xBF"));  // lead
1051         assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF");
1052
1053         let mut string = Wtf8Buf::new();
1054         string.push_wtf8(w(b"\xED\xA0\x80"));  // lead
1055         string.push_wtf8(w(b"\xEE\x80\x80"));  // not surrogate
1056         assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80");
1057
1058         let mut string = Wtf8Buf::new();
1059         string.push_wtf8(w(b"\xED\x9F\xBF"));  // not surrogate
1060         string.push_wtf8(w(b"\xED\xB0\x80"));  // trail
1061         assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80");
1062
1063         let mut string = Wtf8Buf::new();
1064         string.push_wtf8(w(b"a"));  // not surrogate, < 3 bytes
1065         string.push_wtf8(w(b"\xED\xB0\x80"));  // trail
1066         assert_eq!(string.bytes, b"\x61\xED\xB0\x80");
1067
1068         let mut string = Wtf8Buf::new();
1069         string.push_wtf8(w(b"\xED\xB0\x80"));  // trail
1070         assert_eq!(string.bytes, b"\xED\xB0\x80");
1071     }
1072
1073     #[test]
1074     fn wtf8buf_truncate() {
1075         let mut string = Wtf8Buf::from_str("aé");
1076         string.truncate(1);
1077         assert_eq!(string.bytes, b"a");
1078     }
1079
1080     #[test]
1081     #[should_panic]
1082     fn wtf8buf_truncate_fail_code_point_boundary() {
1083         let mut string = Wtf8Buf::from_str("aé");
1084         string.truncate(2);
1085     }
1086
1087     #[test]
1088     #[should_panic]
1089     fn wtf8buf_truncate_fail_longer() {
1090         let mut string = Wtf8Buf::from_str("aé");
1091         string.truncate(4);
1092     }
1093
1094     #[test]
1095     fn wtf8buf_into_string() {
1096         let mut string = Wtf8Buf::from_str("aé 💩");
1097         assert_eq!(string.clone().into_string(), Ok(String::from("aé 💩")));
1098         string.push(CodePoint::from_u32(0xD800).unwrap());
1099         assert_eq!(string.clone().into_string(), Err(string));
1100     }
1101
1102     #[test]
1103     fn wtf8buf_into_string_lossy() {
1104         let mut string = Wtf8Buf::from_str("aé 💩");
1105         assert_eq!(string.clone().into_string_lossy(), String::from("aé 💩"));
1106         string.push(CodePoint::from_u32(0xD800).unwrap());
1107         assert_eq!(string.clone().into_string_lossy(), String::from("aé 💩�"));
1108     }
1109
1110     #[test]
1111     fn wtf8buf_from_iterator() {
1112         fn f(values: &[u32]) -> Wtf8Buf {
1113             values.iter().map(|&c| CodePoint::from_u32(c).unwrap()).collect::<Wtf8Buf>()
1114         }
1115         assert_eq!(f(&[0x61, 0xE9, 0x20, 0x1F4A9]).bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
1116
1117         assert_eq!(f(&[0xD83D, 0xDCA9]).bytes, b"\xF0\x9F\x92\xA9");  // Magic!
1118         assert_eq!(f(&[0xD83D, 0x20, 0xDCA9]).bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
1119         assert_eq!(f(&[0xD800, 0xDBFF]).bytes, b"\xED\xA0\x80\xED\xAF\xBF");
1120         assert_eq!(f(&[0xD800, 0xE000]).bytes, b"\xED\xA0\x80\xEE\x80\x80");
1121         assert_eq!(f(&[0xD7FF, 0xDC00]).bytes, b"\xED\x9F\xBF\xED\xB0\x80");
1122         assert_eq!(f(&[0x61, 0xDC00]).bytes, b"\x61\xED\xB0\x80");
1123         assert_eq!(f(&[0xDC00]).bytes, b"\xED\xB0\x80");
1124     }
1125
1126     #[test]
1127     fn wtf8buf_extend() {
1128         fn e(initial: &[u32], extended: &[u32]) -> Wtf8Buf {
1129             fn c(value: &u32) -> CodePoint { CodePoint::from_u32(*value).unwrap() }
1130             let mut string = initial.iter().map(c).collect::<Wtf8Buf>();
1131             string.extend(extended.iter().map(c));
1132             string
1133         }
1134
1135         assert_eq!(e(&[0x61, 0xE9], &[0x20, 0x1F4A9]).bytes,
1136                    b"a\xC3\xA9 \xF0\x9F\x92\xA9");
1137
1138         assert_eq!(e(&[0xD83D], &[0xDCA9]).bytes, b"\xF0\x9F\x92\xA9");  // Magic!
1139         assert_eq!(e(&[0xD83D, 0x20], &[0xDCA9]).bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
1140         assert_eq!(e(&[0xD800], &[0xDBFF]).bytes, b"\xED\xA0\x80\xED\xAF\xBF");
1141         assert_eq!(e(&[0xD800], &[0xE000]).bytes, b"\xED\xA0\x80\xEE\x80\x80");
1142         assert_eq!(e(&[0xD7FF], &[0xDC00]).bytes, b"\xED\x9F\xBF\xED\xB0\x80");
1143         assert_eq!(e(&[0x61], &[0xDC00]).bytes, b"\x61\xED\xB0\x80");
1144         assert_eq!(e(&[], &[0xDC00]).bytes, b"\xED\xB0\x80");
1145     }
1146
1147     #[test]
1148     fn wtf8buf_show() {
1149         let mut string = Wtf8Buf::from_str("a\té \u{7f}💩\r");
1150         string.push(CodePoint::from_u32(0xD800).unwrap());
1151         assert_eq!(format!("{:?}", string), "\"a\\té \\u{7f}\u{1f4a9}\\r\\u{d800}\"");
1152     }
1153
1154     #[test]
1155     fn wtf8buf_as_slice() {
1156         assert_eq!(Wtf8Buf::from_str("aé").as_slice(), Wtf8::from_str("aé"));
1157     }
1158
1159     #[test]
1160     fn wtf8buf_show_str() {
1161         let text = "a\té 💩\r";
1162         let string = Wtf8Buf::from_str(text);
1163         assert_eq!(format!("{:?}", text), format!("{:?}", string));
1164     }
1165
1166     #[test]
1167     fn wtf8_from_str() {
1168         assert_eq!(&Wtf8::from_str("").bytes, b"");
1169         assert_eq!(&Wtf8::from_str("aé 💩").bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
1170     }
1171
1172     #[test]
1173     fn wtf8_len() {
1174         assert_eq!(Wtf8::from_str("").len(), 0);
1175         assert_eq!(Wtf8::from_str("aé 💩").len(), 8);
1176     }
1177
1178     #[test]
1179     fn wtf8_slice() {
1180         assert_eq!(&Wtf8::from_str("aé 💩")[1.. 4].bytes, b"\xC3\xA9 ");
1181     }
1182
1183     #[test]
1184     #[should_panic]
1185     fn wtf8_slice_not_code_point_boundary() {
1186         &Wtf8::from_str("aé 💩")[2.. 4];
1187     }
1188
1189     #[test]
1190     fn wtf8_slice_from() {
1191         assert_eq!(&Wtf8::from_str("aé 💩")[1..].bytes, b"\xC3\xA9 \xF0\x9F\x92\xA9");
1192     }
1193
1194     #[test]
1195     #[should_panic]
1196     fn wtf8_slice_from_not_code_point_boundary() {
1197         &Wtf8::from_str("aé 💩")[2..];
1198     }
1199
1200     #[test]
1201     fn wtf8_slice_to() {
1202         assert_eq!(&Wtf8::from_str("aé 💩")[..4].bytes, b"a\xC3\xA9 ");
1203     }
1204
1205     #[test]
1206     #[should_panic]
1207     fn wtf8_slice_to_not_code_point_boundary() {
1208         &Wtf8::from_str("aé 💩")[5..];
1209     }
1210
1211     #[test]
1212     fn wtf8_ascii_byte_at() {
1213         let slice = Wtf8::from_str("aé 💩");
1214         assert_eq!(slice.ascii_byte_at(0), b'a');
1215         assert_eq!(slice.ascii_byte_at(1), b'\xFF');
1216         assert_eq!(slice.ascii_byte_at(2), b'\xFF');
1217         assert_eq!(slice.ascii_byte_at(3), b' ');
1218         assert_eq!(slice.ascii_byte_at(4), b'\xFF');
1219     }
1220
1221     #[test]
1222     fn wtf8_code_points() {
1223         fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() }
1224         fn cp(string: &Wtf8Buf) -> Vec<Option<char>> {
1225             string.code_points().map(|c| c.to_char()).collect::<Vec<_>>()
1226         }
1227         let mut string = Wtf8Buf::from_str("é ");
1228         assert_eq!(cp(&string), [Some('é'), Some(' ')]);
1229         string.push(c(0xD83D));
1230         assert_eq!(cp(&string), [Some('é'), Some(' '), None]);
1231         string.push(c(0xDCA9));
1232         assert_eq!(cp(&string), [Some('é'), Some(' '), Some('💩')]);
1233     }
1234
1235     #[test]
1236     fn wtf8_as_str() {
1237         assert_eq!(Wtf8::from_str("").as_str(), Some(""));
1238         assert_eq!(Wtf8::from_str("aé 💩").as_str(), Some("aé 💩"));
1239         let mut string = Wtf8Buf::new();
1240         string.push(CodePoint::from_u32(0xD800).unwrap());
1241         assert_eq!(string.as_str(), None);
1242     }
1243
1244     #[test]
1245     fn wtf8_to_string_lossy() {
1246         assert_eq!(Wtf8::from_str("").to_string_lossy(), Cow::Borrowed(""));
1247         assert_eq!(Wtf8::from_str("aé 💩").to_string_lossy(), Cow::Borrowed("aé 💩"));
1248         let mut string = Wtf8Buf::from_str("aé 💩");
1249         string.push(CodePoint::from_u32(0xD800).unwrap());
1250         let expected: Cow<str> = Cow::Owned(String::from("aé 💩�"));
1251         assert_eq!(string.to_string_lossy(), expected);
1252     }
1253
1254     #[test]
1255     fn wtf8_display() {
1256         fn d(b: &[u8]) -> String {
1257             format!("{}", &unsafe { Wtf8::from_bytes_unchecked(b) })
1258         }
1259
1260         assert_eq!("", d("".as_bytes()));
1261         assert_eq!("aé 💩", d("aé 💩".as_bytes()));
1262
1263         let mut string = Wtf8Buf::from_str("aé 💩");
1264         string.push(CodePoint::from_u32(0xD800).unwrap());
1265         assert_eq!("aé 💩�", d(string.as_inner()));
1266     }
1267
1268     #[test]
1269     fn wtf8_encode_wide() {
1270         let mut string = Wtf8Buf::from_str("aé ");
1271         string.push(CodePoint::from_u32(0xD83D).unwrap());
1272         string.push_char('💩');
1273         assert_eq!(string.encode_wide().collect::<Vec<_>>(),
1274                    vec![0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]);
1275     }
1276 }