decoded_char/
lib.rs

1//! This is a very simple utility crate that provides a wrapper over `char`
2//! values, `DecodedChar`, additionally storing the original byte length of the
3//! character in the encoded source file.
4//!
5//! It also provides wrappers around `char` iterators to produce `DecodedChar`
6//! iterators from UTF-8/16 encoded sources.
7use std::borrow::Borrow;
8use std::ops::Deref;
9
10/// Decoded character.
11///
12/// A character and its original byte length in the encoded source file.
13#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
14pub struct DecodedChar {
15	/// Character.
16	c: char,
17
18	/// Byte length in the encoded source file.
19	len: usize,
20}
21
22impl DecodedChar {
23	/// Creates a new decoded character from its value, `c`,
24	/// and its original byte length `len` in the encoded source file.
25	#[inline(always)]
26	pub fn new(c: char, len: usize) -> Self {
27		Self { c, len }
28	}
29
30	/// Creates a new decoded character,
31	/// decoded from an UTF-8 encoded source file.
32	#[inline(always)]
33	pub fn from_utf8(c: char) -> Self {
34		Self {
35			c,
36			len: c.len_utf8(),
37		}
38	}
39
40	/// Creates a new decoded character,
41	/// decoded from an UTF-16 encoded source file.
42	#[inline(always)]
43	pub fn from_utf16(c: char) -> Self {
44		Self {
45			c,
46			len: c.len_utf16(),
47		}
48	}
49
50	/// Returns the character.
51	#[inline(always)]
52	pub fn chr(&self) -> char {
53		self.c
54	}
55
56	/// Returns the original byte length of the character in the encoded source
57	/// file.
58	#[inline(always)]
59	#[allow(clippy::len_without_is_empty)]
60	pub fn len(&self) -> usize {
61		self.len
62	}
63
64	/// Turns this `DecodedChar` into the underlying `char`.
65	#[inline(always)]
66	pub fn into_char(self) -> char {
67		self.c
68	}
69
70	/// Turns this `DecodedChar` into the original byte length in the encoded
71	/// source file.
72	#[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/// Iterator wrapper around UTF-8 encoded sources.
116#[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/// Iterator wrapper around fallible UTF-8 encoded sources.
136#[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/// Iterator wrapper around UTF-16 encoded sources.
158#[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/// Iterator wrapper around fallible UTF-16 encoded sources.
178#[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
199/// Extension for `str` providing the `decoded_char` method.
200pub trait DecodedChars {
201	/// Returns an iterator over the UTF-8 decoded characters of the string,
202	/// wrapped inside a `DecodedChar`.
203	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}