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