1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub struct FacetCaps {
11 pub scalable: bool,
13 pub copyable: bool,
15 pub pasteable: bool,
17 pub cuttable: bool,
19 pub selectable: bool,
21 pub themeable: bool,
23 pub resizable: bool,
25 pub searchable: bool,
27 pub editable: bool,
30 pub navigable: bool,
34 pub draggable: bool,
38 pub time_scrollable: bool,
42}
43
44impl Default for FacetCaps {
45 fn default() -> Self {
46 Self::NONE
47 }
48}
49
50impl FacetCaps {
51 pub const NONE: Self = Self {
53 scalable: false,
54 copyable: false,
55 pasteable: false,
56 cuttable: false,
57 selectable: false,
58 themeable: false,
59 resizable: false,
60 searchable: false,
61 editable: false,
62 navigable: false,
63 draggable: false,
64 time_scrollable: false,
65 };
66
67 pub const ALL: Self = Self {
69 scalable: true,
70 copyable: true,
71 pasteable: true,
72 cuttable: true,
73 selectable: true,
74 themeable: true,
75 resizable: true,
76 searchable: true,
77 editable: true,
78 navigable: true,
79 draggable: true,
80 time_scrollable: true,
81 };
82
83 pub const fn scalable(mut self) -> Self {
85 self.scalable = true;
86 self
87 }
88 pub const fn copyable(mut self) -> Self {
89 self.copyable = true;
90 self
91 }
92 pub const fn pasteable(mut self) -> Self {
93 self.pasteable = true;
94 self
95 }
96 pub const fn cuttable(mut self) -> Self {
98 self.cuttable = true;
99 self.copyable = true;
100 self
101 }
102 pub const fn selectable(mut self) -> Self {
103 self.selectable = true;
104 self
105 }
106 pub const fn themeable(mut self) -> Self {
107 self.themeable = true;
108 self
109 }
110 pub const fn resizable(mut self) -> Self {
111 self.resizable = true;
112 self
113 }
114 pub const fn searchable(mut self) -> Self {
115 self.searchable = true;
116 self
117 }
118 pub const fn editable(mut self) -> Self {
119 self.editable = true;
120 self
121 }
122 pub const fn navigable(mut self) -> Self {
123 self.navigable = true;
124 self
125 }
126 pub const fn draggable(mut self) -> Self {
128 self.draggable = true;
129 self
130 }
131 pub const fn time_scrollable(mut self) -> Self {
133 self.time_scrollable = true;
134 self
135 }
136
137 pub fn to_json(self) -> serde_json::Value {
139 serde_json::json!({
140 "scalable": self.scalable, "copyable": self.copyable,
141 "pasteable": self.pasteable, "cuttable": self.cuttable,
142 "selectable": self.selectable, "themeable": self.themeable,
143 "resizable": self.resizable, "searchable": self.searchable,
144 "editable": self.editable, "navigable": self.navigable,
145 "draggable": self.draggable, "time_scrollable": self.time_scrollable,
146 })
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn none_is_all_false_and_equals_default() {
156 let n = FacetCaps::NONE;
157 assert!(!n.scalable && !n.copyable && !n.pasteable && !n.cuttable);
158 assert!(!n.selectable && !n.themeable && !n.resizable && !n.searchable);
159 assert!(!n.editable && !n.navigable && !n.draggable && !n.time_scrollable);
160 assert_eq!(FacetCaps::default(), FacetCaps::NONE);
161 }
162
163 #[test]
164 fn all_is_all_true() {
165 let a = FacetCaps::ALL;
166 assert!(a.scalable && a.copyable && a.pasteable && a.cuttable);
167 assert!(a.selectable && a.themeable && a.resizable && a.searchable);
168 assert!(a.editable && a.navigable && a.draggable && a.time_scrollable);
169 }
170
171 #[test]
172 fn builders_set_exactly_one_flag() {
173 assert_eq!(FacetCaps::NONE.scalable(), FacetCaps { scalable: true, ..FacetCaps::NONE });
174 assert_eq!(FacetCaps::NONE.selectable(), FacetCaps { selectable: true, ..FacetCaps::NONE });
175 assert_eq!(FacetCaps::NONE.searchable(), FacetCaps { searchable: true, ..FacetCaps::NONE });
176 assert_eq!(FacetCaps::NONE.editable(), FacetCaps { editable: true, ..FacetCaps::NONE });
177 assert_eq!(FacetCaps::NONE.draggable(), FacetCaps { draggable: true, ..FacetCaps::NONE });
178 assert_eq!(
179 FacetCaps::NONE.time_scrollable(),
180 FacetCaps { time_scrollable: true, ..FacetCaps::NONE }
181 );
182 }
183
184 #[test]
185 fn cuttable_implies_copyable() {
186 let c = FacetCaps::NONE.cuttable();
187 assert!(c.cuttable && c.copyable, "cut implies copy");
188 }
189
190 #[test]
191 fn builders_chain_in_const_context() {
192 const C: FacetCaps = FacetCaps::NONE.selectable().copyable().searchable().scalable().resizable().editable();
193 assert!(C.selectable && C.copyable && C.searchable && C.scalable && C.resizable && C.editable);
194 assert!(!C.pasteable && !C.cuttable && !C.themeable);
195 }
196
197 #[test]
198 fn to_json_carries_every_flag() {
199 let j = FacetCaps::NONE.scalable().themeable().editable().to_json();
200 assert_eq!(j["scalable"], true);
201 assert_eq!(j["themeable"], true);
202 assert_eq!(j["editable"], true);
203 assert_eq!(j["copyable"], false);
204 assert_eq!(j["navigable"], false);
205 assert_eq!(j["draggable"], false);
206 assert_eq!(j["time_scrollable"], false);
207 assert_eq!(j.as_object().unwrap().len(), 12);
209 }
210}