1 //! UTF-8 and UTF-16 decoding iterators
5 use super::from_u32_unchecked;
7 /// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
9 /// This `struct` is created by the [`decode_utf16`] method on [`char`]. See its
10 /// documentation for more.
12 /// [`decode_utf16`]: char::decode_utf16
13 #[stable(feature = "decode_utf16", since = "1.9.0")]
14 #[derive(Clone, Debug)]
15 pub struct DecodeUtf16<I>
17 I: Iterator<Item = u16>,
23 /// An error that can be returned when decoding UTF-16 code points.
25 /// This `struct` is created when using the [`DecodeUtf16`] type.
26 #[stable(feature = "decode_utf16", since = "1.9.0")]
27 #[derive(Debug, Clone, Eq, PartialEq)]
28 pub struct DecodeUtf16Error {
32 /// Creates an iterator over the UTF-16 encoded code points in `iter`,
33 /// returning unpaired surrogates as `Err`s.
40 /// use std::char::decode_utf16;
42 /// // 𝄞mus<invalid>ic<invalid>
44 /// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
48 /// decode_utf16(v.iter().cloned())
49 /// .map(|r| r.map_err(|e| e.unpaired_surrogate()))
50 /// .collect::<Vec<_>>(),
53 /// Ok('m'), Ok('u'), Ok('s'),
61 /// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
64 /// use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
66 /// // 𝄞mus<invalid>ic<invalid>
68 /// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
72 /// decode_utf16(v.iter().cloned())
73 /// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
74 /// .collect::<String>(),
78 #[stable(feature = "decode_utf16", since = "1.9.0")]
80 pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
81 DecodeUtf16 { iter: iter.into_iter(), buf: None }
84 #[stable(feature = "decode_utf16", since = "1.9.0")]
85 impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
86 type Item = Result<char, DecodeUtf16Error>;
88 fn next(&mut self) -> Option<Result<char, DecodeUtf16Error>> {
89 let u = match self.buf.take() {
91 None => self.iter.next()?,
94 if !u.is_utf16_surrogate() {
95 // SAFETY: not a surrogate
96 Some(Ok(unsafe { from_u32_unchecked(u as u32) }))
97 } else if u >= 0xDC00 {
98 // a trailing surrogate
99 Some(Err(DecodeUtf16Error { code: u }))
101 let u2 = match self.iter.next() {
104 None => return Some(Err(DecodeUtf16Error { code: u })),
106 if u2 < 0xDC00 || u2 > 0xDFFF {
107 // not a trailing surrogate so we're not a valid
108 // surrogate pair, so rewind to redecode u2 next time.
110 return Some(Err(DecodeUtf16Error { code: u }));
113 // all ok, so lets decode it.
114 let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000;
115 // SAFETY: we checked that it's a legal unicode value
116 Some(Ok(unsafe { from_u32_unchecked(c) }))
121 fn size_hint(&self) -> (usize, Option<usize>) {
122 let (low, high) = self.iter.size_hint();
124 let (low_buf, high_buf) = match self.buf {
125 // buf is empty, no additional elements from it.
127 // `u` is a non surrogate, so it's always an additional character.
128 Some(u) if !u.is_utf16_surrogate() => (1, 1),
129 // `u` is a leading surrogate (it can never be a trailing surrogate and
130 // it's a surrogate due to the previous branch) and `self.iter` is empty.
132 // `u` can't be paired, since the `self.iter` is empty,
133 // so it will always become an additional element (error).
134 Some(_u) if high == Some(0) => (1, 1),
135 // `u` is a leading surrogate and `iter` may be non-empty.
137 // `u` can either pair with a trailing surrogate, in which case no additional elements
138 // are produced, or it can become an error, in which case it's an additional character (error).
142 // `self.iter` could contain entirely valid surrogates (2 elements per
143 // char), or entirely non-surrogates (1 element per char).
145 // On odd lower bound, at least one element must stay unpaired
146 // (with other elements from `self.iter`), so we round up.
147 let low = low.div_ceil(2) + low_buf;
148 let high = high.and_then(|h| h.checked_add(high_buf));
154 impl DecodeUtf16Error {
155 /// Returns the unpaired surrogate which caused this error.
157 #[stable(feature = "decode_utf16", since = "1.9.0")]
158 pub fn unpaired_surrogate(&self) -> u16 {
163 #[stable(feature = "decode_utf16", since = "1.9.0")]
164 impl fmt::Display for DecodeUtf16Error {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 write!(f, "unpaired surrogate found: {:x}", self.code)