1 | use std::ops::{BitAnd, BitOr, BitXor};
|
2 |
|
3 | use crate::style::Attribute;
|
4 |
|
5 | /// a bitset for all possible attributes
|
6 | #[derive (Debug, Default, Clone, Copy, PartialEq, Eq)]
|
7 | pub struct Attributes(u32);
|
8 |
|
9 | impl From<Attribute> for Attributes {
|
10 | fn from(attribute: Attribute) -> Self {
|
11 | Self(attribute.bytes())
|
12 | }
|
13 | }
|
14 |
|
15 | impl From<&[Attribute]> for Attributes {
|
16 | fn from(arr: &[Attribute]) -> Self {
|
17 | let mut attributes: Attributes = Attributes::default();
|
18 | for &attr: Attribute in arr {
|
19 | attributes.set(attribute:attr);
|
20 | }
|
21 | attributes
|
22 | }
|
23 | }
|
24 |
|
25 | impl BitAnd<Attribute> for Attributes {
|
26 | type Output = Self;
|
27 | fn bitand(self, rhs: Attribute) -> Self {
|
28 | Self(self.0 & rhs.bytes())
|
29 | }
|
30 | }
|
31 | impl BitAnd for Attributes {
|
32 | type Output = Self;
|
33 | fn bitand(self, rhs: Self) -> Self {
|
34 | Self(self.0 & rhs.0)
|
35 | }
|
36 | }
|
37 |
|
38 | impl BitOr<Attribute> for Attributes {
|
39 | type Output = Self;
|
40 | fn bitor(self, rhs: Attribute) -> Self {
|
41 | Self(self.0 | rhs.bytes())
|
42 | }
|
43 | }
|
44 | impl BitOr for Attributes {
|
45 | type Output = Self;
|
46 | fn bitor(self, rhs: Self) -> Self {
|
47 | Self(self.0 | rhs.0)
|
48 | }
|
49 | }
|
50 |
|
51 | impl BitXor<Attribute> for Attributes {
|
52 | type Output = Self;
|
53 | fn bitxor(self, rhs: Attribute) -> Self {
|
54 | Self(self.0 ^ rhs.bytes())
|
55 | }
|
56 | }
|
57 | impl BitXor for Attributes {
|
58 | type Output = Self;
|
59 | fn bitxor(self, rhs: Self) -> Self {
|
60 | Self(self.0 ^ rhs.0)
|
61 | }
|
62 | }
|
63 |
|
64 | impl Attributes {
|
65 | /// Sets the attribute.
|
66 | /// If it's already set, this does nothing.
|
67 | #[inline (always)]
|
68 | pub fn set(&mut self, attribute: Attribute) {
|
69 | self.0 |= attribute.bytes();
|
70 | }
|
71 |
|
72 | /// Unsets the attribute.
|
73 | /// If it's not set, this changes nothing.
|
74 | #[inline (always)]
|
75 | pub fn unset(&mut self, attribute: Attribute) {
|
76 | self.0 &= !attribute.bytes();
|
77 | }
|
78 |
|
79 | /// Sets the attribute if it's unset, unset it
|
80 | /// if it is set.
|
81 | #[inline (always)]
|
82 | pub fn toggle(&mut self, attribute: Attribute) {
|
83 | self.0 ^= attribute.bytes();
|
84 | }
|
85 |
|
86 | /// Returns whether the attribute is set.
|
87 | #[inline (always)]
|
88 | pub const fn has(self, attribute: Attribute) -> bool {
|
89 | self.0 & attribute.bytes() != 0
|
90 | }
|
91 |
|
92 | /// Sets all the passed attributes. Removes none.
|
93 | #[inline (always)]
|
94 | pub fn extend(&mut self, attributes: Attributes) {
|
95 | self.0 |= attributes.0;
|
96 | }
|
97 |
|
98 | /// Returns whether there is no attribute set.
|
99 | #[inline (always)]
|
100 | pub const fn is_empty(self) -> bool {
|
101 | self.0 == 0
|
102 | }
|
103 | }
|
104 |
|
105 | #[cfg (test)]
|
106 | mod tests {
|
107 | use super::{Attribute, Attributes};
|
108 |
|
109 | #[test ]
|
110 | fn test_attributes() {
|
111 | let mut attributes: Attributes = Attribute::Bold.into();
|
112 | assert!(attributes.has(Attribute::Bold));
|
113 | attributes.set(Attribute::Italic);
|
114 | assert!(attributes.has(Attribute::Italic));
|
115 | attributes.unset(Attribute::Italic);
|
116 | assert!(!attributes.has(Attribute::Italic));
|
117 | attributes.toggle(Attribute::Bold);
|
118 | assert!(attributes.is_empty());
|
119 | }
|
120 | }
|
121 | |