diff options
| author | M Farkas-Dyck <mfdyck@google.com> | 2016-05-27 08:16:27 -0800 |
|---|---|---|
| committer | M Farkas-Dyck <mfdyck@google.com> | 2016-07-13 17:40:16 -0800 |
| commit | 837029fec146b4eb7af4dae3f002b00306af00db (patch) | |
| tree | d7a90d713528de58ee67a2956fead015ec8b0155 /src/libcore | |
| parent | fe96928d7de991e527a7ed7b88bb30aa965c8a08 (diff) | |
| download | rust-837029fec146b4eb7af4dae3f002b00306af00db.tar.gz rust-837029fec146b4eb7af4dae3f002b00306af00db.zip | |
add core::char::DecodeUtf8
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/char.rs | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/libcore/char.rs b/src/libcore/char.rs index d80b456181a..0e7f04c7758 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -676,3 +676,50 @@ impl Iterator for EncodeUtf16 { self.as_slice().iter().size_hint() } } + + +/// An iterator over an iterator of bytes of the characters the bytes represent +/// as UTF-8 +#[unstable(feature = "decode_utf8", issue = "33906")] +#[derive(Clone, Debug)] +pub struct DecodeUtf8<I: Iterator<Item = u8>>(::iter::Peekable<I>); + +/// Decodes an `Iterator` of bytes as UTF-8. +#[unstable(feature = "decode_utf8", issue = "33906")] +#[inline] +pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter> { + DecodeUtf8(i.into_iter().peekable()) +} + +/// `<DecodeUtf8 as Iterator>::next` returns this for an invalid input sequence. +#[unstable(feature = "decode_utf8", issue = "33906")] +#[derive(PartialEq, Debug)] +pub struct InvalidSequence(()); + +#[unstable(feature = "decode_utf8", issue = "33906")] +impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> { + type Item = Result<char, InvalidSequence>; + #[inline] + fn next(&mut self) -> Option<Result<char, InvalidSequence>> { + self.0.next().map(|b| { + if b & 0x80 == 0 { Ok(b as char) } else { + let l = (!b).leading_zeros() as usize; // number of bytes in UTF-8 representation + if l < 2 || l > 6 { return Err(InvalidSequence(())) }; + let mut x = (b as u32) & (0x7F >> l); + for _ in 0..l-1 { + match self.0.peek() { + Some(&b) if b & 0xC0 == 0x80 => { + self.0.next(); + x = (x << 6) | (b as u32) & 0x3F; + }, + _ => return Err(InvalidSequence(())), + } + } + match from_u32(x) { + Some(x) if l == x.len_utf8() => Ok(x), + _ => Err(InvalidSequence(())), + } + } + }) + } +} |
