Skip to main content

nonzero_char/
iter.rs

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        // SAFETY: create this iter by NonZeroChar::MIN
11        unsafe { NonZeroChar::new_unchecked(ch) }
12    })
13}
14
15/// This struct is created by the [`iter_inclusive`] method on [`NonZeroChar`].
16/// See its documentation for more.
17///
18/// [`iter_inclusive`]: NonZeroChar::iter_inclusive
19#[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/// Decode Utf16 errors, created by the [`DecodeUtf16::next`]
94#[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    /// Returns the unpaired surrogate which caused this error.
107    pub fn unpaired_surrogate(&self) -> Option<u16> {
108        self.error.as_ref()
109            .map(|e| e.unpaired_surrogate())
110    }
111
112    /// Returns error code
113    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/// This struct is created by the [`decode_utf16`] method on [`NonZeroChar`].
140/// See its documentation for more.
141///
142/// [`decode_utf16`]: NonZeroChar::decode_utf16
143#[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}