encode_unicode/
traits.rs

1/* Copyright 2016 The encode_unicode Developers
2 *
3 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 * http://opensource.org/licenses/MIT>, at your option. This file may not be
6 * copied, modified, or distributed except according to those terms.
7 */
8
9#![allow(unused_unsafe)]// explicit unsafe{} blocks in unsafe functions are a good thing.
10
11use utf8_char::Utf8Char;
12use utf16_char::Utf16Char;
13use utf8_iterators::*;
14use utf16_iterators::*;
15use decoding_iterators::*;
16use error::*;
17extern crate core;
18use self::core::{char, u32, mem};
19use self::core::ops::{Not, Index, RangeFull};
20use self::core::borrow::Borrow;
21#[cfg(feature="ascii")]
22extern crate ascii;
23#[cfg(feature="ascii")]
24use self::ascii::AsciiStr;
25
26// TODO better docs and tests
27
28/// Methods for working with `u8`s as UTF-8 bytes.
29pub trait U8UtfExt {
30    /// How many more bytes will you need to complete this codepoint?
31    ///
32    /// # Errors
33    ///
34    /// An error is returned if the byte is not a valid start of an UTF-8
35    /// codepoint:
36    ///
37    /// * `128..192`: ContinuationByte
38    /// * `248..`: TooLongSequence
39    ///
40    /// Values in 244..248 represent a too high codepoint, but do not cause an
41    /// error.
42    fn extra_utf8_bytes(self) -> Result<usize,InvalidUtf8FirstByte>;
43
44    /// How many more bytes will you need to complete this codepoint?
45    ///
46    /// This function assumes that the byte is a valid UTF-8 start, and might
47    /// return any value otherwise. (but the function is pure and safe to call
48    /// with any value).
49    fn extra_utf8_bytes_unchecked(self) -> usize;
50}
51
52impl U8UtfExt for u8 {
53    #[inline]
54    fn extra_utf8_bytes(self) -> Result<usize,InvalidUtf8FirstByte> {
55        use error::InvalidUtf8FirstByte::{ContinuationByte,TooLongSeqence};
56        // the bit twiddling is explained in extra_utf8_bytes_unchecked()
57        if self < 128 {
58            return Ok(0);
59        }
60        match ((self as u32)<<25).not().leading_zeros() {
61            n @ 1...3 => Ok(n as usize),
62            0 => Err(ContinuationByte),
63            _ => Err(TooLongSeqence),
64        }
65    }
66    #[inline]
67    fn extra_utf8_bytes_unchecked(self) -> usize {
68        // For fun I've optimized this function (for x86 instruction count):
69        // The most straightforward implementation, that lets the compiler do
70        // the optimizing:
71        //match self {
72        //    0b0000_0000...0b0111_1111 => 0,
73        //    0b1100_0010...0b1101_1111 => 1,
74        //    0b1110_0000...0b1110_1111 => 2,
75        //    0b1111_0000...0b1111_0100 => 3,
76        //                _             => whatever()
77        //}
78        // Using `unsafe{self::core::hint::unreachable_unchecked()}` for the
79        // "don't care" case is a terrible idea: while having the function
80        // non-deterministically return whatever happens to be in a register
81        // MIGHT be acceptable, it permits the function to not `ret`urn at all,
82        // but let execution fall through to whatever comes after it in the
83        // binary! (in other words completely UB).
84        // Currently unreachable_unchecked() might trap too,
85        // which is certainly not what we want.
86        // I also think `unsafe{mem::unitialized()}` is much more likely to
87        // explicitly produce whatever happens to be in a register than tell
88        // the compiler it can ignore this branch but needs to produce a value.
89        //
90        // From the bit patterns we see that for non-ASCII values the result is
91        // (number of leading set bits) - 1
92        // The standard library doesn't have a method for counting leading ones,
93        // but it has leading_zeros(), which can be used after inverting.
94        // This function can therefore be reduced to the one-liner
95        //`self.not().leading_zeros().saturating_sub(1) as usize`, which would
96        // be branchless for architectures with instructions for
97        // leading_zeros() and saturating_sub().
98
99        // Shortest version as long as ASCII-ness can be predicted: (especially
100        // if the BSR instruction which leading_zeros() uses is microcoded or
101        // doesn't exist)
102        // u8.leading_zeros() would cast to a bigger type internally, so that's
103        // free. compensating by shifting left by 24 before inverting lets the
104        // compiler know that the value passed to leading_zeros() is not zero,
105        // for which BSR's output is undefined and leading_zeros() normally has
106        // special case with a branch.
107        // Shifting one bit too many left acts as a saturating_sub(1).
108        if self<128 {0} else {((self as u32)<<25).not().leading_zeros() as usize}
109
110        // Branchless but longer version: (9 instructions)
111        // It's tempting to try (self|0x80).not().leading_zeros().wrapping_sub(1),
112        // but that produces high lengths for ASCII values 0b01xx_xxxx.
113        // If we could somehow (branchlessy) clear that bit for ASCII values...
114        // We can by masking with the value shifted right with sign extension!
115        // (any nonzero number of bits in range works)
116        //let extended = self as i8 as i32;
117        //let ascii_cleared = (extended<<25) & (extended>>25);
118        //ascii_cleared.not().leading_zeros() as usize
119
120        // cmov version: (7 instructions)
121        //(((self as u32)<<24).not().leading_zeros() as usize).saturating_sub(1)
122    }
123}
124
125
126/// Methods for working with `u16`s as UTF-16 units.
127pub trait U16UtfExt {
128    /// Will you need an extra unit to complete this codepoint?
129    ///
130    /// Returns `Err` for trailing surrogates, `Ok(true)` for leading surrogates,
131    /// and `Ok(false)` for others.
132    fn utf16_needs_extra_unit(self) -> Result<bool,InvalidUtf16FirstUnit>;
133
134    /// Does this `u16` need another `u16` to complete a codepoint?
135    /// Returns `(self & 0xfc00) == 0xd800`
136    ///
137    /// Is basically an unchecked variant of `utf16_needs_extra_unit()`.
138    fn is_utf16_leading_surrogate(self) -> bool;
139}
140impl U16UtfExt for u16 {
141    #[inline]
142    fn utf16_needs_extra_unit(self) -> Result<bool,InvalidUtf16FirstUnit> {
143        match self {
144            // https://en.wikipedia.org/wiki/UTF-16#U.2B10000_to_U.2B10FFFF
145            0x00_00...0xd7_ff | 0xe0_00...0xff_ff => Ok(false),
146            0xd8_00...0xdb_ff => Ok(true),
147                    _         => Err(InvalidUtf16FirstUnit)
148        }
149    }
150    #[inline]
151    fn is_utf16_leading_surrogate(self) -> bool {
152        (self & 0xfc00) == 0xd800// Clear the ten content bytes of a surrogate,
153                                 // and see if it's a leading surrogate.
154    }
155}
156
157
158
159
160/// Extension trait for `char` that adds methods for converting to and from UTF-8 or UTF-16.
161pub trait CharExt: Sized {
162    /// Get the UTF-8 representation of this codepoint.
163    ///
164    /// `Utf8Char` is to `[u8;4]` what `char` is to `u32`:
165    /// a restricted type that cannot be mutated internally.
166    fn to_utf8(self) -> Utf8Char;
167
168    /// Get the UTF-16 representation of this codepoint.
169    ///
170    /// `Utf16Char` is to `[u16;2]` what `char` is to `u32`:
171    /// a restricted type that cannot be mutated internally.
172    fn to_utf16(self) -> Utf16Char;
173
174    /// Iterate over or [read](https://doc.rust-lang.org/std/io/trait.Read.html)
175    /// the one to four bytes in the UTF-8 representation of this codepoint.
176    ///
177    /// An identical alternative to the unstable `char.encode_utf8()`.
178    /// That method somehow still exist on stable, so I have to use a different name.
179    fn iter_utf8_bytes(self) -> Utf8Iterator;
180
181    /// Iterate over the one or two units in the UTF-16 representation of this codepoint.
182    ///
183    /// An identical alternative to the unstable `char.encode_utf16()`.
184    /// That method somehow still exist on stable, so I have to use a different name.
185    fn iter_utf16_units(self) -> Utf16Iterator;
186
187
188    /// Convert this char to an UTF-8 array, and also return how many bytes of
189    /// the array are used,
190    ///
191    /// The returned array is left-aligned with unused bytes set to zero.
192    fn to_utf8_array(self) -> ([u8; 4], usize);
193
194    /// Convert this `char` to UTF-16.
195    /// The second `u16` is `Some` if a surrogate pair is required.
196    fn to_utf16_tuple(self) -> (u16, Option<u16>);
197
198
199
200    /// Create a `char` from the start of an UTF-8 slice,
201    /// and also return how many bytes were used.
202    ///
203    /// # Errors
204    ///
205    /// Returns an `Err` if the slice is empty, doesn't start with a valid
206    /// UTF-8 sequence or is too short for the sequence.
207    ///
208    /// # Examples
209    ///
210    /// ```
211    /// use encode_unicode::CharExt;
212    /// use encode_unicode::error::InvalidUtf8Slice::*;
213    /// use encode_unicode::error::InvalidUtf8::*;
214    ///
215    /// assert_eq!(char::from_utf8_slice_start(&[b'A', b'B', b'C']), Ok(('A',1)));
216    /// assert_eq!(char::from_utf8_slice_start(&[0xdd, 0xbb]), Ok(('\u{77b}',2)));
217    ///
218    /// assert_eq!(char::from_utf8_slice_start(&[]), Err(TooShort(1)));
219    /// assert_eq!(char::from_utf8_slice_start(&[0xf0, 0x99]), Err(TooShort(4)));
220    /// assert_eq!(char::from_utf8_slice_start(&[0xee, b'F', 0x80]), Err(Utf8(NotAContinuationByte(1))));
221    /// assert_eq!(char::from_utf8_slice_start(&[0xee, 0x99, 0x0f]), Err(Utf8(NotAContinuationByte(2))));
222    /// ```
223    fn from_utf8_slice_start(src: &[u8]) -> Result<(Self,usize),InvalidUtf8Slice>;
224
225    /// Create a `char` from the start of an UTF-16 slice,
226    /// and also return how many units were used.
227    ///
228    /// If you want to continue after an error, continue with the next `u16` unit.
229    fn from_utf16_slice_start(src: &[u16]) -> Result<(Self,usize), InvalidUtf16Slice>;
230
231
232    /// Convert an UTF-8 sequence as returned from `.to_utf8_array()` into a `char`
233    ///
234    /// The codepoint must start at the first byte, and leftover bytes are ignored.
235    ///
236    /// # Errors
237    ///
238    /// Returns an `Err` if the array doesn't start with a valid UTF-8 sequence.
239    ///
240    /// # Examples
241    ///
242    /// ```
243    /// use encode_unicode::CharExt;
244    /// use encode_unicode::error::InvalidUtf8Array::*;
245    /// use encode_unicode::error::InvalidUtf8::*;
246    /// use encode_unicode::error::InvalidCodepoint::*;
247    ///
248    /// assert_eq!(char::from_utf8_array([b'A', 0, 0, 0]), Ok('A'));
249    /// assert_eq!(char::from_utf8_array([0xf4, 0x8b, 0xbb, 0xbb]), Ok('\u{10befb}'));
250    /// assert_eq!(char::from_utf8_array([b'A', b'B', b'C', b'D']), Ok('A'));
251    /// assert_eq!(char::from_utf8_array([0, 0, 0xcc, 0xbb]), Ok('\0'));
252    ///
253    /// assert_eq!(char::from_utf8_array([0xef, b'F', 0x80, 0x80]), Err(Utf8(NotAContinuationByte(1))));
254    /// assert_eq!(char::from_utf8_array([0xc1, 0x80, 0, 0]), Err(Utf8(OverLong)));
255    /// assert_eq!(char::from_utf8_array([0xf7, 0xaa, 0x99, 0x88]), Err(Codepoint(TooHigh)));
256    /// ```
257    fn from_utf8_array(utf8: [u8; 4]) -> Result<Self,InvalidUtf8Array>;
258
259    /// Convert a UTF-16 pair as returned from `.to_utf16_tuple()` into a `char`.
260    fn from_utf16_tuple(utf16: (u16, Option<u16>)) -> Result<Self, InvalidUtf16Tuple>;
261
262
263    /// Convert an UTF-8 sequence into a char.
264    ///
265    /// The length of the slice is taken as length of the sequence;
266    /// it should be 1,2,3 or 4.
267    ///
268    /// # Safety
269    ///
270    /// The slice must contain exactly one, valid, UTF-8 sequence.
271    ///
272    /// Passing a slice that produces an invalid codepoint is always undefined
273    /// behavior; Later checks that the codepoint is valid can be removed
274    /// by the compiler.
275    ///
276    /// # Panics
277    ///
278    /// If the slice is empty
279    unsafe fn from_utf8_exact_slice_unchecked(src: &[u8]) -> Self;
280
281    /// Convert a UTF-16 tuple as returned from `.to_utf16_tuple()` into a `char`.
282    unsafe fn from_utf16_tuple_unchecked(utf16: (u16, Option<u16>)) -> Self;
283
284
285    /// Perform some extra validations compared to `char::from_u32_unchecked()`
286    ///
287    /// # Errors
288    ///
289    /// This function will return an error if
290    ///
291    /// * the value is greater than 0x10ffff
292    /// * the value is between 0xd800 and 0xdfff (inclusive)
293    fn from_u32_detailed(c: u32) -> Result<Self,InvalidCodepoint>;
294}
295
296
297
298impl CharExt for char {
299      /////////
300     //UTF-8//
301    /////////
302
303    fn to_utf8(self) -> Utf8Char {
304        self.into()
305    }
306    fn iter_utf8_bytes(self) -> Utf8Iterator {
307        self.to_utf8().into_iter()
308    }
309
310    fn to_utf8_array(self) -> ([u8; 4], usize) {
311        let len = self.len_utf8();
312        let mut c = self as u32;
313        if len == 1 {// ASCII, the common case
314            ([c as u8, 0, 0, 0],  1)
315        } else {
316            let mut parts = 0;// convert to 6-bit bytes
317                        parts |= c & 0x3f;  c>>=6;
318            parts<<=8;  parts |= c & 0x3f;  c>>=6;
319            parts<<=8;  parts |= c & 0x3f;  c>>=6;
320            parts<<=8;  parts |= c & 0x3f;
321            parts |= 0x80_80_80_80;// set the most significant bit
322            parts >>= 8*(4-len);// right-align bytes
323            // Now, unused bytes are zero, (which matters for Utf8Char.eq())
324            // and the rest are 0b10xx_xxxx
325
326            // set header on first byte
327            parts |= (0xff_00u32 >> len)  &  0xff;// store length
328            parts &= Not::not(1u32 << 7-len);// clear the next bit after it
329
330            let bytes: [u8; 4] = unsafe{ mem::transmute(u32::from_le(parts)) };
331            (bytes, len)
332        }
333    }
334
335
336    fn from_utf8_slice_start(src: &[u8]) -> Result<(Self,usize),InvalidUtf8Slice> {
337        use errors::InvalidUtf8::*;
338        use errors::InvalidUtf8Slice::*;
339        let first = match src.first() {
340            Some(first) => *first,
341            None => return Err(TooShort(1)),
342        };
343        let bytes = match first.extra_utf8_bytes() {
344            Err(e)    => return Err(Utf8(FirstByte(e))),
345            Ok(0)     => return Ok((first as char, 1)),
346            Ok(extra) if extra >= src.len()
347                      => return Err(TooShort(extra+1)),
348            Ok(extra) => &src[..extra+1],
349        };
350        if let Some(i) = bytes.iter().skip(1).position(|&b| (b >> 6) != 0b10 ) {
351            Err(Utf8(NotAContinuationByte(i+1)))
352        } else if overlong(bytes[0], bytes[1]) {
353            Err(Utf8(OverLong))
354        } else {
355            match char::from_u32_detailed(merge_nonascii_unchecked_utf8(bytes)) {
356                Ok(c) => Ok((c, bytes.len())),
357                Err(e) => Err(Codepoint(e)),
358            }
359        }
360    }
361
362    fn from_utf8_array(utf8: [u8; 4]) -> Result<Self,InvalidUtf8Array> {
363        use errors::InvalidUtf8::*;
364        use errors::InvalidUtf8Array::*;
365        let src = match utf8[0].extra_utf8_bytes() {
366            Err(error) => return Err(Utf8(FirstByte(error))),
367            Ok(0)      => return Ok(utf8[0] as char),
368            Ok(extra)  => &utf8[..extra+1],
369        };
370        if let Some(i) = src[1..].iter().position(|&b| (b >> 6) != 0b10 ) {
371            Err(Utf8(NotAContinuationByte(i+1)))
372        } else if overlong(utf8[0], utf8[1]) {
373            Err(Utf8(OverLong))
374        } else {
375            char::from_u32_detailed(merge_nonascii_unchecked_utf8(src))
376                 .map_err(|e| Codepoint(e) )
377        }
378    }
379
380    unsafe fn from_utf8_exact_slice_unchecked(src: &[u8]) -> Self {
381        if src.len() == 1 {
382            src[0] as char
383        } else {
384            char::from_u32_unchecked(merge_nonascii_unchecked_utf8(src))
385        }
386    }
387
388
389
390      //////////
391     //UTF-16//
392    //////////
393
394    fn to_utf16(self) -> Utf16Char {
395        Utf16Char::from(self)
396    }
397    fn iter_utf16_units(self) -> Utf16Iterator {
398        self.to_utf16().into_iter()
399    }
400
401    fn to_utf16_tuple(self) -> (u16, Option<u16>) {
402        let c = self as u32;
403        if c <= 0x_ff_ff {// single (or reserved, which we ignore)
404            (c as u16, None)
405        } else {// double (or too high, which we ignore)
406            let c = c - 0x_01_00_00;
407            let high = 0x_d8_00 + (c >> 10);
408            let low = 0x_dc_00 + (c & 0x_03_ff);
409            (high as u16,  Some(low as u16))
410        }
411    }
412
413
414    fn from_utf16_slice_start(src: &[u16]) -> Result<(Self,usize), InvalidUtf16Slice> {
415        use errors::InvalidUtf16Slice::*;
416        unsafe {match (src.get(0), src.get(1)) {
417            (Some(&u @ 0x00_00...0xd7_ff), _) |
418            (Some(&u @ 0xe0_00...0xff_ff), _)
419                => Ok((char::from_u32_unchecked(u as u32), 1)),
420            (Some(&0xdc_00...0xdf_ff), _) => Err(FirstLowSurrogate),
421            (None, _) => Err(EmptySlice),
422            (Some(&f @ 0xd8_00...0xdb_ff), Some(&s @ 0xdc_00...0xdf_ff))
423                => Ok((char::from_utf16_tuple_unchecked((f, Some(s))), 2)),
424            (Some(&0xd8_00...0xdb_ff), Some(_)) => Err(SecondNotLowSurrogate),
425            (Some(&0xd8_00...0xdb_ff), None) => Err(MissingSecond),
426            (Some(_), _) => unreachable!()
427        }}
428    }
429
430    fn from_utf16_tuple(utf16: (u16, Option<u16>)) -> Result<Self, InvalidUtf16Tuple> {
431        use errors::InvalidUtf16Tuple::*;
432        unsafe{ match utf16 {
433            (0x00_00...0xd7_ff, None) | // single
434            (0xe0_00...0xff_ff, None) | // single
435            (0xd8_00...0xdb_ff, Some(0xdc_00...0xdf_ff)) // correct surrogate
436                => Ok(char::from_utf16_tuple_unchecked(utf16)),
437            (0xd8_00...0xdb_ff, Some(_)) => Err(InvalidSecond),
438            (0xd8_00...0xdb_ff, None   ) => Err(MissingSecond),
439            (0xdc_00...0xdf_ff,    _   ) => Err(FirstIsTrailingSurrogate),
440            (        _        , Some(_)) => Err(SuperfluousSecond),
441            (        _        , None   ) => unreachable!()
442        }}
443    }
444
445    unsafe fn from_utf16_tuple_unchecked(utf16: (u16, Option<u16>)) -> Self {
446        match utf16.1 {
447            Some(second) => combine_surrogates(utf16.0, second),
448            None         => char::from_u32_unchecked(utf16.0 as u32)
449        }
450    }
451
452
453    fn from_u32_detailed(c: u32) -> Result<Self,InvalidCodepoint> {
454        match char::from_u32(c) {
455            Some(c) => Ok(c),
456            None if c > 0x10_ff_ff => Err(InvalidCodepoint::TooHigh),
457            None => Err(InvalidCodepoint::Utf16Reserved),
458        }
459    }
460}
461
462// Adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c
463fn overlong(first: u8, second: u8) -> bool {
464    if first < 0x80 {
465        false
466    } else if (first & 0xe0) == 0xc0 {
467        (first & 0xfe) == 0xc0
468    } else if (first & 0xf0) == 0xe0 {
469        first == 0xe0 && (second & 0xe0) == 0x80
470    } else {
471        first == 0xf0 && (second & 0xf0) == 0x80
472    }
473}
474
475/// Decodes the codepoint represented by a multi-byte UTF-8 sequence.
476///
477/// Does not check that the codepoint is valid,
478/// and returns `u32` because casting invalid codepoints to `char` is insta UB.
479fn merge_nonascii_unchecked_utf8(src: &[u8]) -> u32 {
480    let mut c = src[0] as u32 & (0x7f >> src.len());
481    for b in &src[1..] {
482        c = (c << 6)  |  (b & 0b0011_1111) as u32;
483    }
484    c
485}
486
487// Create a `char` from a leading and a trailing surrogate.
488unsafe fn combine_surrogates(first: u16, second: u16) -> char {
489    let high = (first & 0x_03_ff) as u32;
490    let low = (second & 0x_03_ff) as u32;
491    let c = ((high << 10) | low) + 0x_01_00_00; // no, the constant can't be or'd in
492    char::from_u32_unchecked(c)
493}
494
495
496
497/// Adds `.utf8chars()` and `.utf16chars()` iterator constructors to `&str`.
498pub trait StrExt: AsRef<str> {
499    /// Equivalent to `.chars()` but produces `Utf8Char`s.
500    fn utf8chars(&self) -> Utf8Chars;
501    /// Equivalent to `.chars()` but produces `Utf16Char`s.
502    fn utf16chars(&self) -> Utf16Chars;
503    /// Equivalent to `.char_indices()` but produces `Utf8Char`s.
504    fn utf8char_indices(&self) -> Utf8CharIndices;
505    /// Equivalent to `.char_indices()` but produces `Utf16Char`s.
506    fn utf16char_indices(&self) -> Utf16CharIndices;
507}
508
509impl StrExt for str {
510    fn utf8chars(&self) -> Utf8Chars {
511        Utf8Chars::from(self)
512    }
513    fn utf16chars(&self) -> Utf16Chars {
514        Utf16Chars::from(self)
515    }
516    fn utf8char_indices(&self) -> Utf8CharIndices {
517        Utf8CharIndices::from(self)
518    }
519    fn utf16char_indices(&self) -> Utf16CharIndices {
520        Utf16CharIndices::from(self)
521    }
522}
523
524#[cfg(feature="ascii")]
525impl StrExt for AsciiStr {
526    fn utf8chars(&self) -> Utf8Chars {
527        Utf8Chars::from(self.as_str())
528    }
529    fn utf16chars(&self) -> Utf16Chars {
530        Utf16Chars::from(self.as_str())
531    }
532    fn utf8char_indices(&self) -> Utf8CharIndices {
533        Utf8CharIndices::from(self.as_str())
534    }
535    fn utf16char_indices(&self) -> Utf16CharIndices {
536        Utf16CharIndices::from(self.as_str())
537    }
538}
539
540
541
542/// Iterator methods that convert between `u8`s and `Utf8Char` or `u16`s and `Utf16Char`
543///
544/// All the iterator adapters also accept iterators that produce references of
545/// the type they convert from.
546pub trait IterExt: Iterator+Sized {
547    /// Converts an iterator of `Utf8Char`s or `&Utf8Char`s to an iterator of
548    /// `u8`s.
549    ///
550    /// Has the same effect as `.flat_map()` or `.flatten()`, but the returned
551    /// iterator is ~40% faster.
552    ///
553    /// The iterator also implements `Read`
554    /// (when the `std` feature isn't disabled).  
555    /// Reading will never produce an error, and calls to `.read()` and `.next()`
556    /// can be mixed.
557    ///
558    /// The exact number of bytes cannot be known in advance, but `size_hint()`
559    /// gives the possible range.
560    /// (min: all remaining characters are ASCII, max: all require four bytes)
561    ///
562    /// # Examples
563    ///
564    /// From iterator of values:
565    ///
566    /// ```
567    /// use encode_unicode::{IterExt, StrExt};
568    ///
569    /// let iterator = "foo".utf8chars();
570    /// let mut bytes = [0; 4];
571    /// for (u,dst) in iterator.to_bytes().zip(&mut bytes) {*dst=u;}
572    /// assert_eq!(&bytes, b"foo\0");
573    /// ```
574    ///
575    /// From iterator of references:
576    ///
577    #[cfg_attr(feature="std", doc=" ```")]
578    #[cfg_attr(not(feature="std"), doc=" ```no_compile")]
579    /// use encode_unicode::{IterExt, StrExt, Utf8Char};
580    ///
581    /// let chars: Vec<Utf8Char> = "💣 bomb 💣".utf8chars().collect();
582    /// let bytes: Vec<u8> = chars.iter().to_bytes().collect();
583    /// let flat_map: Vec<u8> = chars.iter().flat_map(|u8c| *u8c ).collect();
584    /// assert_eq!(bytes, flat_map);
585    /// ```
586    ///
587    /// `Read`ing from it:
588    ///
589    #[cfg_attr(feature="std", doc=" ```")]
590    #[cfg_attr(not(feature="std"), doc=" ```no_compile")]
591    /// use encode_unicode::{IterExt, StrExt};
592    /// use std::io::Read;
593    ///
594    /// let s = "Ååh‽";
595    /// assert_eq!(s.len(), 8);
596    /// let mut buf = [b'E'; 9];
597    /// let mut reader = s.utf8chars().to_bytes();
598    /// assert_eq!(reader.read(&mut buf[..]).unwrap(), 8);
599    /// assert_eq!(reader.read(&mut buf[..]).unwrap(), 0);
600    /// assert_eq!(&buf[..8], s.as_bytes());
601    /// assert_eq!(buf[8], b'E');
602    /// ```
603    fn to_bytes(self) -> Utf8CharSplitter<Self::Item,Self> where Self::Item: Borrow<Utf8Char>;
604
605    /// Converts an iterator of `Utf16Char` (or `&Utf16Char`) to an iterator of
606    /// `u16`s.
607    ///
608    /// Has the same effect as `.flat_map()` or `.flatten()`, but the returned
609    /// iterator is about twice as fast.
610    ///
611    /// The exact number of units cannot be known in advance, but `size_hint()`
612    /// gives the possible range.
613    ///
614    /// # Examples
615    ///
616    /// From iterator of values:
617    ///
618    /// ```
619    /// use encode_unicode::{IterExt, StrExt};
620    ///
621    /// let iterator = "foo".utf16chars();
622    /// let mut units = [0; 4];
623    /// for (u,dst) in iterator.to_units().zip(&mut units) {*dst=u;}
624    ///
625    /// assert_eq!(units, ['f' as u16, 'o' as u16, 'o' as u16, 0]);
626    /// ```
627    ///
628    /// From iterator of references:
629    ///
630    #[cfg_attr(feature="std", doc=" ```")]
631    #[cfg_attr(not(feature="std"), doc=" ```no_compile")]
632    /// use encode_unicode::{IterExt, StrExt, Utf16Char};
633    ///
634    /// // (💣 takes two units)
635    /// let chars: Vec<Utf16Char> = "💣 bomb 💣".utf16chars().collect();
636    /// let units: Vec<u16> = chars.iter().to_units().collect();
637    /// let flat_map: Vec<u16> = chars.iter().flat_map(|u16c| *u16c ).collect();
638    ///
639    /// assert_eq!(units, flat_map);
640    /// ```
641    fn to_units(self) -> Utf16CharSplitter<Self::Item,Self> where Self::Item: Borrow<Utf16Char>;
642
643    /// Decodes bytes as UTF-8 and groups them into `Utf8Char`s
644    ///
645    /// When errors (invalid values or sequences) are encountered,
646    /// it continues with the byte right after the start of the error sequence.  
647    /// This is neither the most intelligent choiche (sometimes it is guaranteed to
648    ///  produce another error), nor the easiest to implement, but I believe it to
649    /// be the most predictable.
650    /// It also means that ASCII characters are never hidden by errors.
651    ///
652    /// # Examples
653    ///
654    /// Replace all errors with u+FFFD REPLACEMENT_CHARACTER:
655    /// ```
656    /// use encode_unicode::{Utf8Char, IterExt};
657    ///
658    /// let mut buf = [b'\0'; 255];
659    /// let len = b"foo\xCFbar".iter()
660    ///     .to_utf8chars()
661    ///     .flat_map(|r| r.unwrap_or(Utf8Char::from('\u{FFFD}')).into_iter() )
662    ///     .zip(&mut buf[..])
663    ///     .map(|(byte, dst)| *dst = byte )
664    ///     .count();
665    ///
666    /// assert_eq!(&buf[..len], "foo\u{FFFD}bar".as_bytes());
667    /// ```
668    ///
669    /// Collect everything up until the first error into a string:
670    #[cfg_attr(feature="std", doc=" ```")]
671    #[cfg_attr(not(feature="std"), doc=" ```no_compile")]
672    /// use encode_unicode::iterator::Utf8CharMerger;
673    /// let mut good = String::new();
674    /// for r in Utf8CharMerger::from(b"foo\xcc\xbbbar\xcc\xddbaz") {
675    ///     if let Ok(uc) = r {
676    ///         good.push_str(uc.as_str());
677    ///     } else {
678    ///         break;
679    ///     }
680    /// }
681    /// assert_eq!(good, "foo̻bar");
682    /// ```
683    ///
684    /// Abort decoding on error:
685    #[cfg_attr(feature="std", doc=" ```")]
686    #[cfg_attr(not(feature="std"), doc=" ```no_compile")]
687    /// use encode_unicode::{IterExt, Utf8Char};
688    /// use encode_unicode::error::{InvalidUtf8Slice, InvalidUtf8};
689    ///
690    /// let result = b"ab\0\xe0\xbc\xa9 \xf3\x80\x77".iter()
691    ///     .to_utf8chars()
692    ///     .collect::<Result<String,InvalidUtf8Slice>>();
693    ///
694    /// assert_eq!(result, Err(InvalidUtf8Slice::Utf8(InvalidUtf8::NotAContinuationByte(2))));
695    /// ```
696    fn to_utf8chars(self) -> Utf8CharMerger<Self::Item,Self> where Self::Item: Borrow<u8>;
697
698    /// Decodes bytes as UTF-16 and groups them into `Utf16Char`s
699    ///
700    /// When errors (unmatched leading surrogates or unexpected trailing surrogates)
701    /// are encountered, an error is produced for every unit.
702    ///
703    /// # Examples
704    ///
705    /// Replace errors with '�':
706    #[cfg_attr(feature="std", doc=" ```")]
707    #[cfg_attr(not(feature="std"), doc=" ```no_compile")]
708    /// use encode_unicode::{IterExt, Utf16Char};
709    ///
710    /// let slice = &['a' as u16, 0xdf00, 0xd83c, 0xdca0][..];
711    /// let string = slice.iter()
712    ///     .to_utf16chars()
713    ///     .map(|r| r.unwrap_or(Utf16Char::from('\u{fffd}')) ) // REPLACEMENT_CHARACTER
714    ///     .collect::<String>();
715    ///
716    /// assert_eq!(string, "a�🂠");
717    /// ```
718    ///
719    /// ```
720    /// use encode_unicode::{IterExt, Utf16Char};
721    /// use encode_unicode::error::Utf16PairError::*;
722    ///
723    /// let slice = [0xdcba, 0xdeff, 0xd8be, 0xdeee, 'Y' as u16, 0xdab1, 0xdab1];
724    /// let mut iter = slice.iter().to_utf16chars();
725    /// assert_eq!(iter.size_hint(), (3, Some(7)));
726    /// assert_eq!(iter.next(), Some(Err(UnexpectedTrailingSurrogate)));
727    /// assert_eq!(iter.next(), Some(Err(UnexpectedTrailingSurrogate)));
728    /// assert_eq!(iter.next(), Some(Ok(Utf16Char::from('\u{3faee}'))));
729    /// assert_eq!(iter.next(), Some(Ok(Utf16Char::from('Y'))));
730    /// assert_eq!(iter.next(), Some(Err(UnmatchedLeadingSurrogate)));
731    /// assert_eq!(iter.next(), Some(Err(Incomplete)));
732    /// assert_eq!(iter.into_remaining_units().next(), None);
733    /// ```
734    ///
735    /// Search for a codepoint and return the codepoint index of the first match:
736    /// ```
737    /// use encode_unicode::{IterExt, Utf16Char};
738    ///
739    /// let position = [0xd875, 0xdd4f, '≈' as u16, '2' as u16].iter()
740    ///     .to_utf16chars()
741    ///     .position(|r| r == Ok(Utf16Char::from('≈')) );
742    ///
743    /// assert_eq!(position, Some(1));
744    /// ```
745    fn to_utf16chars(self) -> Utf16CharMerger<Self::Item,Self> where Self::Item: Borrow<u16>;
746}
747
748impl<I:Iterator> IterExt for I {
749    fn to_bytes(self) -> Utf8CharSplitter<Self::Item,Self> where Self::Item: Borrow<Utf8Char> {
750        iter_bytes(self)
751    }
752    fn to_units(self) -> Utf16CharSplitter<Self::Item,Self> where Self::Item: Borrow<Utf16Char> {
753        iter_units(self)
754    }
755    fn to_utf8chars(self) -> Utf8CharMerger<Self::Item,Self> where Self::Item: Borrow<u8> {
756        Utf8CharMerger::from(self)
757    }
758    fn to_utf16chars(self) -> Utf16CharMerger<Self::Item,Self> where Self::Item: Borrow<u16> {
759        Utf16CharMerger::from(self)
760    }
761}
762
763
764/// Methods for iterating over `u8` and `u16` slices as UTF-8 or UTF-16 characters.
765///
766/// The iterators are slightly faster than the similar methods in [`IterExt`](trait.IterExt.html)
767/// because they con "push back" items for free after errors and don't need a
768/// separate buffer that must be checked on every call to `.next()`.
769pub trait SliceExt: Index<RangeFull> {
770    /// Decode `u8` slices as UTF-8 and iterate over the codepoints as `Utf8Char`s,
771    ///
772    /// # Examples
773    ///
774    /// Get the index and error type of the first error:
775    #[cfg_attr(feature="std", doc=" ```")]
776    #[cfg_attr(not(feature="std"), doc=" ```no_compile")]
777    /// use encode_unicode::{SliceExt, Utf8Char};
778    /// use encode_unicode::error::InvalidUtf8Slice;
779    ///
780    /// let slice = b"ab\0\xe0\xbc\xa9 \xf3\x80\x77";
781    /// let result = slice.utf8char_indices()
782    ///     .map(|(offset,r,length)| r.map_err(|e| (offset,e,length) ) )
783    ///     .collect::<Result<String,(usize,InvalidUtf8Slice,usize)>>();
784    ///
785    /// assert_eq!(result, Err((7, InvalidUtf8Slice::TooShort(4), 1)));
786    /// ```
787    ///
788    /// ```
789    /// use encode_unicode::{SliceExt, Utf8Char};
790    /// use std::error::Error;
791    ///
792    /// let slice = b"\xf0\xbf\xbf\xbfXY\xdd\xbb\xe1\x80\x99quux123";
793    /// let mut fixed_size = [Utf8Char::default(); 8];
794    /// for (cp_i, (byte_index, r, _)) in slice.utf8char_indices().enumerate().take(8) {
795    ///     match r {
796    ///         Ok(u8c) => fixed_size[cp_i] = u8c,
797    ///         Err(e) => panic!("Invalid codepoint at index {} ({})", cp_i, e.description()),
798    ///     }
799    /// }
800    /// let chars = ['\u{3ffff}', 'X', 'Y', '\u{77b}', '\u{1019}', 'q', 'u', 'u'];
801    /// assert_eq!(fixed_size, chars);
802    /// ```
803    ///
804    #[cfg_attr(feature="std", doc=" ```")]
805    #[cfg_attr(not(feature="std"), doc=" ```no_compile")]
806    /// use encode_unicode::{SliceExt, Utf8Char};
807    /// use encode_unicode::error::InvalidUtf8Slice::*;
808    /// use encode_unicode::error::{InvalidUtf8, InvalidUtf8FirstByte, InvalidCodepoint};
809    ///
810    /// let bytes = b"\xfa-\xf4\x8f\xee\xa1\x8f-\xed\xa9\x87\xf0\xcc\xbb";
811    /// let mut errors = Vec::new();
812    /// let mut lengths = Vec::new();
813    /// let mut string = String::new();
814    /// for (offset,result,length) in bytes.utf8char_indices() {
815    ///     lengths.push((offset,length));
816    ///     let c = result.unwrap_or_else(|error| {
817    ///         errors.push((offset,error));
818    ///         Utf8Char::from('\u{fffd}') // replacement character
819    ///     });
820    ///     string.push_str(c.as_str());
821    /// }
822    ///
823    /// assert_eq!(string, "�-��\u{e84f}-����\u{33b}");
824    /// assert_eq!(lengths, [(0,1), (1,1), (2,1), (3,1), (4,3), (7,1),
825    ///                      (8,1), (9,1), (10,1), (11,1), (12,2)]);
826    /// assert_eq!(errors, [
827    ///     ( 0, Utf8(InvalidUtf8::FirstByte(InvalidUtf8FirstByte::TooLongSeqence))),
828    ///     ( 2, Utf8(InvalidUtf8::NotAContinuationByte(2))),
829    ///     ( 3, Utf8(InvalidUtf8::FirstByte(InvalidUtf8FirstByte::ContinuationByte))),
830    ///     ( 8, Codepoint(InvalidCodepoint::Utf16Reserved)),
831    ///     ( 9, Utf8(InvalidUtf8::FirstByte(InvalidUtf8FirstByte::ContinuationByte))),
832    ///     (10, Utf8(InvalidUtf8::FirstByte(InvalidUtf8FirstByte::ContinuationByte))),
833    ///     (11, TooShort(4)), // (but it was not the last element returned!)
834    /// ]);
835    /// ```
836    fn utf8char_indices(&self) -> Utf8CharDecoder where Self::Output: Borrow<[u8]>;
837
838
839    /// Decode `u16` slices as UTF-16 and iterate over the codepoints as `Utf16Char`s,
840    ///
841    /// The iterator produces `(usize,Result<Utf16Char,Utf16Error>,usize)`,
842    /// and the slice is validated as you go.
843    ///
844    /// The first `usize` contains the offset from the start of the slice and
845    /// the last `usize` contains the length of the codepoint or error.
846    /// The length is either 1 or 2, and always 1 for errors.
847    ///
848    /// # Examples
849    ///
850    #[cfg_attr(feature="std", doc=" ```")]
851    #[cfg_attr(not(feature="std"), doc=" ```no_compile")]
852    /// use encode_unicode::{SliceExt, Utf8Char};
853    ///
854    /// let slice = &['a' as u16, 0xdf00, 0xd83c, 0xdca0][..];
855    /// let mut errors = Vec::new();
856    /// let string = slice.utf16char_indices().map(|(offset,r,_)| match r {
857    ///     Ok(u16c) => Utf8Char::from(u16c),
858    ///     Err(_) => {
859    ///         errors.push(offset);
860    ///         Utf8Char::from('\u{fffd}') // REPLACEMENT_CHARACTER
861    ///     }
862    /// }).collect::<String>();
863    ///
864    /// assert_eq!(string, "a�🂠");
865    /// assert_eq!(errors, [1]);
866    /// ```
867    ///
868    /// Search for a codepoint and return its unit and codepoint index.
869    /// ```
870    /// use encode_unicode::{SliceExt, Utf16Char};
871    ///
872    /// let slice = [0xd875,/*'𝕏'*/ 0xdd4f, '≈' as u16, '2' as u16];
873    /// let position = slice.utf16char_indices()
874    ///     .enumerate()
875    ///     .find(|&(_,(_,r,_))| r == Ok(Utf16Char::from('≈')) )
876    ///     .map(|(codepoint, (offset, _, _))| (codepoint, offset) );
877    ///
878    /// assert_eq!(position, Some((1,2)));
879    /// ```
880    ///
881    /// Error types:
882    /// ```
883    /// use encode_unicode::{SliceExt, Utf16Char};
884    /// use encode_unicode::error::Utf16PairError::*;
885    ///
886    /// let slice = [0xdcba, 0xdeff, 0xd8be, 0xdeee, 'λ' as u16, 0xdab1, 0xdab1];
887    /// let mut iter = slice.utf16char_indices();
888    /// assert_eq!(iter.next(), Some((0, Err(UnexpectedTrailingSurrogate), 1)));
889    /// assert_eq!(iter.next(), Some((1, Err(UnexpectedTrailingSurrogate), 1)));
890    /// assert_eq!(iter.next(), Some((2, Ok(Utf16Char::from('\u{3faee}')), 2)));
891    /// assert_eq!(iter.next(), Some((4, Ok(Utf16Char::from('λ')), 1)));
892    /// assert_eq!(iter.next(), Some((5, Err(UnmatchedLeadingSurrogate), 1)));
893    /// assert_eq!(iter.next(), Some((6, Err(Incomplete), 1)));
894    /// assert_eq!(iter.next(), None);
895    /// assert_eq!(iter.as_slice(), [])
896    /// ```
897    fn utf16char_indices(&self) -> Utf16CharDecoder where Self::Output: Borrow<[u16]>;
898}
899
900impl<S: ?Sized+Index<RangeFull>> SliceExt for S {
901    fn utf8char_indices(&self) -> Utf8CharDecoder where Self::Output: Borrow<[u8]> {
902        Utf8CharDecoder::from(self[..].borrow())
903    }
904    fn utf16char_indices(&self) -> Utf16CharDecoder where Self::Output: Borrow<[u16]> {
905        Utf16CharDecoder::from(self[..].borrow())
906    }
907}