1#[derive(#[automatically_derived]
impl ::core::marker::Copy for Effects { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Effects {
#[inline]
fn clone(&self) -> Effects {
let _: ::core::clone::AssertParamIsClone<u16>;
*self
}
}Clone, #[automatically_derived]
impl ::core::default::Default for Effects {
#[inline]
fn default() -> Effects { Effects(::core::default::Default::default()) }
}Default, #[automatically_derived]
impl ::core::cmp::PartialEq for Effects {
#[inline]
fn eq(&self, other: &Effects) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Effects {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u16>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Effects {
#[inline]
fn partial_cmp(&self, other: &Effects)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Effects {
#[inline]
fn cmp(&self, other: &Effects) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord, #[automatically_derived]
impl ::core::hash::Hash for Effects {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}Hash)]
9pub struct Effects(u16);
10
11impl Effects {
12 const PLAIN: Self = Effects(0);
14
15 #[allow(missing_docs)]
16 pub const BOLD: Self = Effects(1 << 0);
17 #[allow(missing_docs)]
18 pub const DIMMED: Self = Effects(1 << 1);
19 pub const ITALIC: Self = Effects(1 << 2);
21 pub const UNDERLINE: Self = Effects(1 << 3);
23 #[allow(missing_docs)]
24 pub const DOUBLE_UNDERLINE: Self = Effects(1 << 4);
25 #[allow(missing_docs)]
26 pub const CURLY_UNDERLINE: Self = Effects(1 << 5);
27 #[allow(missing_docs)]
28 pub const DOTTED_UNDERLINE: Self = Effects(1 << 6);
29 #[allow(missing_docs)]
30 pub const DASHED_UNDERLINE: Self = Effects(1 << 7);
31 #[allow(missing_docs)]
32 pub const BLINK: Self = Effects(1 << 8);
33 pub const INVERT: Self = Effects(1 << 9);
35 #[allow(missing_docs)]
36 pub const HIDDEN: Self = Effects(1 << 10);
37 pub const STRIKETHROUGH: Self = Effects(1 << 11);
39
40 #[inline]
48 pub const fn new() -> Self {
49 Self::PLAIN
50 }
51
52 #[inline]
64 pub const fn is_plain(self) -> bool {
65 self.0 == Self::PLAIN.0
66 }
67
68 #[inline(always)]
80 pub const fn contains(self, other: Effects) -> bool {
81 (other.0 & self.0) == other.0
82 }
83
84 #[inline(always)]
96 #[must_use]
97 pub const fn insert(mut self, other: Effects) -> Self {
98 self.0 |= other.0;
99 self
100 }
101
102 #[inline(always)]
112 #[must_use]
113 pub const fn remove(mut self, other: Effects) -> Self {
114 self.0 &= !other.0;
115 self
116 }
117
118 #[inline(always)]
125 #[must_use]
126 pub const fn clear(self) -> Self {
127 Self::new()
128 }
129
130 #[inline]
139 #[must_use]
140 pub const fn set(self, other: Self, enable: bool) -> Self {
141 if enable {
142 self.insert(other)
143 } else {
144 self.remove(other)
145 }
146 }
147
148 #[inline(always)]
150 pub fn iter(self) -> EffectIter {
151 EffectIter {
152 index: 0,
153 effects: self,
154 }
155 }
156
157 #[inline(always)]
159 pub(crate) fn index_iter(self) -> EffectIndexIter {
160 EffectIndexIter {
161 index: 0,
162 effects: self,
163 }
164 }
165
166 #[inline]
168 pub fn render(self) -> impl core::fmt::Display + Copy {
169 EffectsDisplay(self)
170 }
171
172 #[inline]
173 #[cfg(feature = "std")]
174 pub(crate) fn write_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
175 for index in self.index_iter() {
176 write.write_all(METADATA[index].escape.as_bytes())?;
177 }
178 Ok(())
179 }
180}
181
182impl core::fmt::Debug for Effects {
192 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
193 f.write_fmt(format_args!("Effects("))write!(f, "Effects(")?;
194 for (i, index) in self.index_iter().enumerate() {
195 if i != 0 {
196 f.write_fmt(format_args!(" | "))write!(f, " | ")?;
197 }
198 f.write_fmt(format_args!("{0}", METADATA[index].name))write!(f, "{}", METADATA[index].name)?;
199 }
200 f.write_fmt(format_args!(")"))write!(f, ")")?;
201 Ok(())
202 }
203}
204
205impl core::ops::BitOr for Effects {
212 type Output = Self;
213
214 #[inline(always)]
215 fn bitor(self, rhs: Self) -> Self {
216 self.insert(rhs)
217 }
218}
219
220impl core::ops::BitOrAssign for Effects {
228 #[inline]
229 fn bitor_assign(&mut self, other: Self) {
230 *self = self.insert(other);
231 }
232}
233
234impl core::ops::Sub for Effects {
241 type Output = Self;
242
243 #[inline]
244 fn sub(self, other: Self) -> Self {
245 self.remove(other)
246 }
247}
248
249impl core::ops::SubAssign for Effects {
257 #[inline]
258 fn sub_assign(&mut self, other: Self) {
259 *self = self.remove(other);
260 }
261}
262
263pub(crate) struct Metadata {
264 pub(crate) name: &'static str,
265 pub(crate) escape: &'static str,
266}
267
268pub(crate) const METADATA: [Metadata; 12] = [
269 Metadata {
270 name: "BOLD",
271 escape: "\u{1b}[1m"escape!("1"),
272 },
273 Metadata {
274 name: "DIMMED",
275 escape: "\u{1b}[2m"escape!("2"),
276 },
277 Metadata {
278 name: "ITALIC",
279 escape: "\u{1b}[3m"escape!("3"),
280 },
281 Metadata {
282 name: "UNDERLINE",
283 escape: "\u{1b}[4m"escape!("4"),
284 },
285 Metadata {
286 name: "DOUBLE_UNDERLINE",
287 escape: "\u{1b}[21m"escape!("21"),
288 },
289 Metadata {
290 name: "CURLY_UNDERLINE",
291 escape: "\u{1b}[4:3m"escape!("4:3"),
292 },
293 Metadata {
294 name: "DOTTED_UNDERLINE",
295 escape: "\u{1b}[4:4m"escape!("4:4"),
296 },
297 Metadata {
298 name: "DASHED_UNDERLINE",
299 escape: "\u{1b}[4:5m"escape!("4:5"),
300 },
301 Metadata {
302 name: "BLINK",
303 escape: "\u{1b}[5m"escape!("5"),
304 },
305 Metadata {
306 name: "INVERT",
307 escape: "\u{1b}[7m"escape!("7"),
308 },
309 Metadata {
310 name: "HIDDEN",
311 escape: "\u{1b}[8m"escape!("8"),
312 },
313 Metadata {
314 name: "STRIKETHROUGH",
315 escape: "\u{1b}[9m"escape!("9"),
316 },
317];
318
319#[derive(#[automatically_derived]
impl ::core::marker::Copy for EffectsDisplay { }Copy, #[automatically_derived]
impl ::core::clone::Clone for EffectsDisplay {
#[inline]
fn clone(&self) -> EffectsDisplay {
let _: ::core::clone::AssertParamIsClone<Effects>;
*self
}
}Clone, #[automatically_derived]
impl ::core::default::Default for EffectsDisplay {
#[inline]
fn default() -> EffectsDisplay {
EffectsDisplay(::core::default::Default::default())
}
}Default, #[automatically_derived]
impl ::core::fmt::Debug for EffectsDisplay {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "EffectsDisplay",
&&self.0)
}
}Debug)]
320struct EffectsDisplay(Effects);
321
322impl core::fmt::Display for EffectsDisplay {
323 #[inline]
324 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
325 for index in self.0.index_iter() {
326 f.write_str(METADATA[index].escape)?;
327 }
328 Ok(())
329 }
330}
331
332#[derive(#[automatically_derived]
impl ::core::clone::Clone for EffectIter {
#[inline]
fn clone(&self) -> EffectIter {
EffectIter {
index: ::core::clone::Clone::clone(&self.index),
effects: ::core::clone::Clone::clone(&self.effects),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for EffectIter {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "EffectIter",
"index", &self.index, "effects", &&self.effects)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for EffectIter {
#[inline]
fn eq(&self, other: &EffectIter) -> bool {
self.index == other.index && self.effects == other.effects
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for EffectIter {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<usize>;
let _: ::core::cmp::AssertParamIsEq<Effects>;
}
}Eq)]
334pub struct EffectIter {
335 index: usize,
336 effects: Effects,
337}
338
339impl Iterator for EffectIter {
340 type Item = Effects;
341
342 fn next(&mut self) -> Option<Self::Item> {
343 while self.index < METADATA.len() {
344 let index = self.index;
345 self.index += 1;
346
347 let effect = Effects(1 << index);
348 if self.effects.contains(effect) {
349 return Some(effect);
350 }
351 }
352
353 None
354 }
355}
356
357#[derive(#[automatically_derived]
impl ::core::clone::Clone for EffectIndexIter {
#[inline]
fn clone(&self) -> EffectIndexIter {
EffectIndexIter {
index: ::core::clone::Clone::clone(&self.index),
effects: ::core::clone::Clone::clone(&self.effects),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for EffectIndexIter {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"EffectIndexIter", "index", &self.index, "effects",
&&self.effects)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for EffectIndexIter {
#[inline]
fn eq(&self, other: &EffectIndexIter) -> bool {
self.index == other.index && self.effects == other.effects
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for EffectIndexIter {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<usize>;
let _: ::core::cmp::AssertParamIsEq<Effects>;
}
}Eq)]
358pub(crate) struct EffectIndexIter {
359 index: usize,
360 effects: Effects,
361}
362
363impl Iterator for EffectIndexIter {
364 type Item = usize;
365
366 fn next(&mut self) -> Option<Self::Item> {
367 while self.index < METADATA.len() {
368 let index = self.index;
369 self.index += 1;
370
371 let effect = Effects(1 << index);
372 if self.effects.contains(effect) {
373 return Some(index);
374 }
375 }
376
377 None
378 }
379}
380
381#[cfg(test)]
382#[cfg(feature = "std")]
383mod test {
384 use super::*;
385
386 #[test]
387 fn print_size_of() {
388 use core::mem::size_of;
389 dbg!(size_of::<Effects>());
390 dbg!(size_of::<EffectsDisplay>());
391 }
392
393 #[test]
394 fn no_align() {
395 #[track_caller]
396 fn assert_no_align(d: impl core::fmt::Display) {
397 let expected = format!("{d}");
398 let actual = format!("{d:<10}");
399 assert_eq!(expected, actual);
400 }
401
402 assert_no_align(Effects::BOLD.render());
403 }
404}