devela/sys/os/term/grid/
style.rs1crate::set! {
7 #[doc = crate::_tags!(term text set)]
8 #[doc = crate::_doc_meta!{
10 location("sys/os/term"),
11 test_size_of(TermStyle = 1|8),
12 }]
13 #[must_use]
16 pub struct TermStyle(u8) {
17 BOLD = 0;
19 ITALIC = 1;
21 UNDERLINE = 2;
23 DIM = 3;
25 BLINK = 4;
27 INVERSE = 5;
29 HIDDEN = 6;
31 CROSSED = 7;
33 }
34 impl {
35 pub const fn extended(self) -> TermStyleExt {
37 TermStyleExt::from_bits(self.bits as u16)
38 }
39 }
40}
41
42crate::set! {
43 #[doc = crate::_tags!(term text set)]
44 #[doc = crate::_doc_meta!{
46 location("sys/os/term"),
47 test_size_of(TermStyleExt = 2|16),
48 }]
49 #[must_use]
53 pub struct TermStyleExt(u16) {
54
55 BOLD = 0;
59 ITALIC = 1;
61 UNDERLINE = 2;
63 DIM = 3;
65 BLINK = 4;
67 INVERSE = 5;
69 HIDDEN = 6;
71 CROSSED = 7;
73
74 BLINK_FAST = 8;
78 FRAKTUR = 9;
80 UNDERLINE_DOUBLE = 10;
82 FRAMED = 11;
84 ENCIRCLED = 12;
86 OVERLINE = 13;
88 SUPERSCRIPT = 14;
90 SUBSCRIPT = 15;
92
93 BASIC = 0..=7;
95 EXTENDED = 8..=15;
97 }
98 impl {
99 pub const fn basic(self) -> TermStyle { TermStyle::from_bits(self.bits as u8) }
101
102 #[must_use]
104 pub const fn is_basic(self) -> bool { !self.intersects(Self::EXTENDED) }
105
106 #[must_use]
108 pub const fn try_basic(self) -> Option<TermStyle> {
109 if self.is_basic() { Some(self.basic()) } else { None }
110 }
111
112 pub const fn extended_only(self) -> Self { self.intersection(Self::EXTENDED) }
114 }
115}
116impl From<TermStyle> for TermStyleExt {
117 fn from(style: TermStyle) -> Self {
118 style.extended()
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::{TermStyle as S, TermStyleExt as X};
125
126 #[test]
127 fn sizes() {
128 assert_eq!(size_of::<S>(), 1);
129 assert_eq!(size_of::<X>(), 2);
130 assert_eq!(size_of::<Option<S>>(), 2);
131 assert_eq!(size_of::<Option<X>>(), 4);
132 }
133 #[test]
134 fn basic_layout_matches() {
135 assert_eq!(S::all().extended(), X::BASIC);
136 assert_eq!(S::BOLD.extended(), X::BOLD);
137 assert_eq!(S::CROSSED.extended(), X::CROSSED);
138 }
139 #[test]
140 fn set_operations() {
141 let style = S::BOLD | S::ITALIC | S::UNDERLINE;
142 assert!(style.contains(S::BOLD | S::ITALIC));
143 assert!(style.intersects(S::UNDERLINE));
144 assert!(!style.intersects(S::BLINK));
145 assert_eq!(style.without(S::ITALIC), S::BOLD | S::UNDERLINE);
146 }
147 #[test]
148 fn extended_partition() {
149 let style = X::BOLD | X::FRAMED | X::OVERLINE;
150 assert_eq!(style.basic(), S::BOLD);
151 assert_eq!(style.extended_only(), X::FRAMED | X::OVERLINE);
152 assert!(!style.is_basic());
153 assert_eq!(style.try_basic(), None);
154 let basic = X::BOLD | X::UNDERLINE;
155 assert!(basic.is_basic());
156 assert_eq!(basic.try_basic(), Some(S::BOLD | S::UNDERLINE));
157 }
158 #[test]
159 fn style_ranges() {
160 assert_eq!(X::BASIC.bits(), 0x00FF);
161 assert_eq!(X::EXTENDED.bits(), 0xFF00);
162 assert_eq!((X::BASIC | X::EXTENDED).bits(), u16::MAX);
163 assert!(!X::BASIC.intersects(X::EXTENDED));
164 }
165}