1use std::borrow::Borrow;
8use std::ops::Deref;
9
10#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
14pub struct DecodedChar {
15 c: char,
17
18 len: usize,
20}
21
22impl DecodedChar {
23 #[inline(always)]
26 pub fn new(c: char, len: usize) -> Self {
27 Self { c, len }
28 }
29
30 #[inline(always)]
33 pub fn from_utf8(c: char) -> Self {
34 Self {
35 c,
36 len: c.len_utf8(),
37 }
38 }
39
40 #[inline(always)]
43 pub fn from_utf16(c: char) -> Self {
44 Self {
45 c,
46 len: c.len_utf16(),
47 }
48 }
49
50 #[inline(always)]
52 pub fn chr(&self) -> char {
53 self.c
54 }
55
56 #[inline(always)]
59 #[allow(clippy::len_without_is_empty)]
60 pub fn len(&self) -> usize {
61 self.len
62 }
63
64 #[inline(always)]
66 pub fn into_char(self) -> char {
67 self.c
68 }
69
70 #[inline(always)]
73 pub fn into_len(self) -> usize {
74 self.len
75 }
76}
77
78impl From<DecodedChar> for char {
79 #[inline(always)]
80 fn from(dc: DecodedChar) -> Self {
81 dc.into_char()
82 }
83}
84
85impl From<DecodedChar> for u32 {
86 #[inline(always)]
87 fn from(dc: DecodedChar) -> Self {
88 dc.into_char().into()
89 }
90}
91
92impl AsRef<char> for DecodedChar {
93 #[inline(always)]
94 fn as_ref(&self) -> &char {
95 &self.c
96 }
97}
98
99impl Borrow<char> for DecodedChar {
100 #[inline(always)]
101 fn borrow(&self) -> &char {
102 &self.c
103 }
104}
105
106impl Deref for DecodedChar {
107 type Target = char;
108
109 #[inline(always)]
110 fn deref(&self) -> &char {
111 &self.c
112 }
113}
114
115#[derive(Clone, Debug)]
117pub struct Utf8Decoded<C>(pub C);
118
119impl<C> Utf8Decoded<C> {
120 #[inline(always)]
121 pub fn new(chars: C) -> Self {
122 Self(chars)
123 }
124}
125
126impl<C: Iterator<Item = char>> Iterator for Utf8Decoded<C> {
127 type Item = DecodedChar;
128
129 #[inline(always)]
130 fn next(&mut self) -> Option<Self::Item> {
131 self.0.next().map(DecodedChar::from_utf8)
132 }
133}
134
135#[derive(Clone, Debug)]
137pub struct FallibleUtf8Decoded<C>(pub C);
138
139impl<C> FallibleUtf8Decoded<C> {
140 #[inline(always)]
141 pub fn new(chars: C) -> Self {
142 Self(chars)
143 }
144}
145
146impl<E, C: Iterator<Item = Result<char, E>>> Iterator for FallibleUtf8Decoded<C> {
147 type Item = Result<DecodedChar, E>;
148
149 #[inline(always)]
150 fn next(&mut self) -> Option<Self::Item> {
151 self.0
152 .next()
153 .map(|result| result.map(DecodedChar::from_utf8))
154 }
155}
156
157#[derive(Clone, Debug)]
159pub struct Utf16Decoded<C>(pub C);
160
161impl<C> Utf16Decoded<C> {
162 #[inline(always)]
163 pub fn new(chars: C) -> Self {
164 Self(chars)
165 }
166}
167
168impl<C: Iterator<Item = char>> Iterator for Utf16Decoded<C> {
169 type Item = DecodedChar;
170
171 #[inline(always)]
172 fn next(&mut self) -> Option<Self::Item> {
173 self.0.next().map(DecodedChar::from_utf16)
174 }
175}
176
177#[derive(Clone, Debug)]
179pub struct FallibleUtf16Decoded<C>(pub C);
180
181impl<C> FallibleUtf16Decoded<C> {
182 #[inline(always)]
183 pub fn new(chars: C) -> Self {
184 Self(chars)
185 }
186}
187
188impl<E, C: Iterator<Item = Result<char, E>>> Iterator for FallibleUtf16Decoded<C> {
189 type Item = Result<DecodedChar, E>;
190
191 #[inline(always)]
192 fn next(&mut self) -> Option<Self::Item> {
193 self.0
194 .next()
195 .map(|result| result.map(DecodedChar::from_utf16))
196 }
197}
198
199pub trait DecodedChars {
201 fn decoded_chars(&self) -> Utf8Decoded<std::str::Chars>;
204}
205
206impl DecodedChars for str {
207 fn decoded_chars(&self) -> Utf8Decoded<std::str::Chars> {
208 Utf8Decoded(self.chars())
209 }
210}