1use crate::NonZeroChar;
2use core::error::Error;
3use core::fmt::Display;
4use core::ops::RangeInclusive;
5use core::iter::FusedIterator;
6
7#[inline]
8fn pack(x: Option<char>) -> Option<NonZeroChar> {
9 x.map(|ch| {
10 unsafe { NonZeroChar::new_unchecked(ch) }
12 })
13}
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub struct RangeInclusiveIter {
21 pub(crate) iter: <RangeInclusive<char> as IntoIterator>::IntoIter,
22}
23
24impl RangeInclusiveIter {
25 pub fn is_empty(&self) -> bool {
26 self.iter.is_empty()
27 }
28
29 pub fn contains<U>(&self, item: &U) -> bool
30 where U: PartialOrd<char> + ?Sized,
31 char: PartialOrd<U>,
32 {
33 self.iter.contains(item)
34 }
35}
36
37impl Default for RangeInclusiveIter {
38 fn default() -> Self {
39 let min = NonZeroChar::MIN.get();
40 let iter = min..=min;
41 Self { iter: iter.into_iter() }
42 }
43}
44
45impl Iterator for RangeInclusiveIter {
46 type Item = NonZeroChar;
47
48 #[inline]
49 fn next(&mut self) -> Option<Self::Item> {
50 pack(self.iter.next())
51 }
52
53 #[inline]
54 fn nth(&mut self, n: usize) -> Option<Self::Item> {
55 pack(self.iter.nth(n))
56 }
57
58 #[inline]
59 fn min(self) -> Option<Self::Item> {
60 pack(self.iter.min())
61 }
62
63 #[inline]
64 fn max(self) -> Option<Self::Item> {
65 pack(self.iter.max())
66 }
67
68 #[inline]
69 fn is_sorted(self) -> bool {
70 self.iter.is_sorted()
71 }
72
73 #[inline]
74 fn size_hint(&self) -> (usize, Option<usize>) {
75 self.iter.size_hint()
76 }
77}
78
79impl DoubleEndedIterator for RangeInclusiveIter {
80 #[inline]
81 fn next_back(&mut self) -> Option<Self::Item> {
82 pack(self.iter.next_back())
83 }
84
85 #[inline]
86 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
87 pack(self.iter.nth_back(n))
88 }
89}
90
91impl FusedIterator for RangeInclusiveIter { }
92
93#[derive(Debug, Clone, PartialEq, Eq)]
95pub struct DecodeUtf16Error {
96 error: Option<core::char::DecodeUtf16Error>,
97}
98
99impl From<core::char::DecodeUtf16Error> for DecodeUtf16Error {
100 fn from(error: core::char::DecodeUtf16Error) -> Self {
101 Self { error: error.into() }
102 }
103}
104
105impl DecodeUtf16Error {
106 pub fn unpaired_surrogate(&self) -> Option<u16> {
108 self.error.as_ref()
109 .map(|e| e.unpaired_surrogate())
110 }
111
112 pub fn code(&self) -> u16 {
114 self.unpaired_surrogate()
115 .unwrap_or(0)
116 }
117}
118
119impl Display for DecodeUtf16Error {
120 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
121 if let Some(e) = &self.error {
122 write!(f, "unpaired surrogate found: {:x}", e.unpaired_surrogate())
123 } else {
124 write!(f, "decode char by zero")
125 }
126 }
127}
128
129impl Error for DecodeUtf16Error {
130 fn description(&self) -> &str {
131 if self.error.is_some() {
132 "unpaired surrogate found"
133 } else {
134 "decode char by zero"
135 }
136 }
137}
138
139#[derive(Debug, Clone)]
144pub struct DecodeUtf16<I: Iterator<Item = u16>> {
145 pub(crate) iter: core::char::DecodeUtf16<I>,
146}
147
148impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
149 type Item = Result<NonZeroChar, DecodeUtf16Error>;
150
151 fn next(&mut self) -> Option<Self::Item> {
152 let ch = self.iter.next()?;
153 ch.map_err(Into::into)
154 .and_then(|ch| NonZeroChar::new(ch)
155 .ok_or(DecodeUtf16Error { error: None }))
156 .into()
157 }
158
159 fn size_hint(&self) -> (usize, Option<usize>) {
160 self.iter.size_hint()
161 }
162}
163
164#[test]
165fn iter_all() {
166 let mut last = '\0';
167 for ch in NonZeroChar::MIN.iter_inclusive(NonZeroChar::MAX) {
168 last = ch.get();
169 }
170 assert_ne!(last, '\0')
171}