nt_string/unicode_string/
iter.rs

1// Copyright 2023 Colin Finck <colin@reactos.org>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3//
4//! Iterator implementations for [`NtUnicodeStr`].
5
6use core::iter::{Copied, FusedIterator};
7use core::slice::Iter;
8
9use widestring::iter::{DecodeUtf16, DecodeUtf16Lossy};
10use widestring::{decode_utf16, decode_utf16_lossy};
11
12use super::NtUnicodeStr;
13use crate::error::Result;
14
15/// An iterator over the UTF-16 decoded [`char`]s of [`NtUnicodeStr`],
16/// which returns an error for unparsed surrogates.
17///
18/// This struct is created by the [`NtUnicodeStr::chars`] method.
19///
20/// [`NtUnicodeStr::chars`]: crate::unicode_string::NtUnicodeStr::chars
21#[derive(Clone, Debug)]
22pub struct Chars<'a> {
23    iter: DecodeUtf16<Copied<Iter<'a, u16>>>,
24}
25
26impl<'a> Chars<'a> {
27    pub(crate) fn new(unicode_str: &'a NtUnicodeStr) -> Self {
28        Self {
29            iter: decode_utf16(unicode_str.u16_iter()),
30        }
31    }
32}
33
34impl<'a> Iterator for Chars<'a> {
35    type Item = Result<char>;
36
37    fn next(&mut self) -> Option<Self::Item> {
38        let result = self.iter.next()?;
39        Some(result.map_err(Into::into))
40    }
41
42    fn size_hint(&self) -> (usize, Option<usize>) {
43        self.iter.size_hint()
44    }
45}
46
47impl<'a> FusedIterator for Chars<'a> {}
48
49impl<'a> DoubleEndedIterator for Chars<'a> {
50    fn next_back(&mut self) -> Option<Self::Item> {
51        let result = self.iter.next_back()?;
52        Some(result.map_err(Into::into))
53    }
54}
55
56/// An iterator over the UTF-16 decoded [`char`]s of [`NtUnicodeStr`],
57/// which automatically replaces unparsed surrogates by [`U+FFFD REPLACEMENT CHARACTER`] (�).
58///
59/// This struct is created by the [`NtUnicodeStr::chars_lossy`] method.
60///
61/// [`NtUnicodeStr::chars_lossy`]: crate::unicode_string::NtUnicodeStr::chars_lossy
62/// [`U+FFFD REPLACEMENT CHARACTER`]: std::char::REPLACEMENT_CHARACTER
63#[derive(Clone, Debug)]
64pub struct CharsLossy<'a> {
65    iter: DecodeUtf16Lossy<Copied<Iter<'a, u16>>>,
66}
67
68impl<'a> CharsLossy<'a> {
69    pub(crate) fn new(unicode_str: &'a NtUnicodeStr) -> Self {
70        Self {
71            iter: decode_utf16_lossy(unicode_str.u16_iter()),
72        }
73    }
74}
75
76impl<'a> Iterator for CharsLossy<'a> {
77    type Item = char;
78
79    fn next(&mut self) -> Option<Self::Item> {
80        self.iter.next()
81    }
82
83    fn size_hint(&self) -> (usize, Option<usize>) {
84        self.iter.size_hint()
85    }
86}
87
88impl<'a> FusedIterator for CharsLossy<'a> {}
89
90impl<'a> DoubleEndedIterator for CharsLossy<'a> {
91    fn next_back(&mut self) -> Option<Self::Item> {
92        self.iter.next_back()
93    }
94}