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}
31
32impl Default for FacetCaps {
33 fn default() -> Self {
34 Self::NONE
35 }
36}
37
38impl FacetCaps {
39 pub const NONE: Self = Self {
41 scalable: false,
42 copyable: false,
43 pasteable: false,
44 cuttable: false,
45 selectable: false,
46 themeable: false,
47 resizable: false,
48 searchable: false,
49 editable: false,
50 };
51
52 pub const ALL: Self = Self {
54 scalable: true,
55 copyable: true,
56 pasteable: true,
57 cuttable: true,
58 selectable: true,
59 themeable: true,
60 resizable: true,
61 searchable: true,
62 editable: true,
63 };
64
65 pub const fn scalable(mut self) -> Self {
67 self.scalable = true;
68 self
69 }
70 pub const fn copyable(mut self) -> Self {
71 self.copyable = true;
72 self
73 }
74 pub const fn pasteable(mut self) -> Self {
75 self.pasteable = true;
76 self
77 }
78 pub const fn cuttable(mut self) -> Self {
80 self.cuttable = true;
81 self.copyable = true;
82 self
83 }
84 pub const fn selectable(mut self) -> Self {
85 self.selectable = true;
86 self
87 }
88 pub const fn themeable(mut self) -> Self {
89 self.themeable = true;
90 self
91 }
92 pub const fn resizable(mut self) -> Self {
93 self.resizable = true;
94 self
95 }
96 pub const fn searchable(mut self) -> Self {
97 self.searchable = true;
98 self
99 }
100 pub const fn editable(mut self) -> Self {
101 self.editable = true;
102 self
103 }
104
105 pub fn to_json(self) -> serde_json::Value {
107 serde_json::json!({
108 "scalable": self.scalable, "copyable": self.copyable,
109 "pasteable": self.pasteable, "cuttable": self.cuttable,
110 "selectable": self.selectable, "themeable": self.themeable,
111 "resizable": self.resizable, "searchable": self.searchable,
112 "editable": self.editable,
113 })
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn none_is_all_false_and_equals_default() {
123 let n = FacetCaps::NONE;
124 assert!(!n.scalable && !n.copyable && !n.pasteable && !n.cuttable);
125 assert!(!n.selectable && !n.themeable && !n.resizable && !n.searchable);
126 assert!(!n.editable);
127 assert_eq!(FacetCaps::default(), FacetCaps::NONE);
128 }
129
130 #[test]
131 fn all_is_all_true() {
132 let a = FacetCaps::ALL;
133 assert!(a.scalable && a.copyable && a.pasteable && a.cuttable);
134 assert!(a.selectable && a.themeable && a.resizable && a.searchable);
135 assert!(a.editable);
136 }
137
138 #[test]
139 fn builders_set_exactly_one_flag() {
140 assert_eq!(FacetCaps::NONE.scalable(), FacetCaps { scalable: true, ..FacetCaps::NONE });
141 assert_eq!(FacetCaps::NONE.selectable(), FacetCaps { selectable: true, ..FacetCaps::NONE });
142 assert_eq!(FacetCaps::NONE.searchable(), FacetCaps { searchable: true, ..FacetCaps::NONE });
143 assert_eq!(FacetCaps::NONE.editable(), FacetCaps { editable: true, ..FacetCaps::NONE });
144 }
145
146 #[test]
147 fn cuttable_implies_copyable() {
148 let c = FacetCaps::NONE.cuttable();
149 assert!(c.cuttable && c.copyable, "cut implies copy");
150 }
151
152 #[test]
153 fn builders_chain_in_const_context() {
154 const C: FacetCaps = FacetCaps::NONE.selectable().copyable().searchable().scalable().resizable().editable();
155 assert!(C.selectable && C.copyable && C.searchable && C.scalable && C.resizable && C.editable);
156 assert!(!C.pasteable && !C.cuttable && !C.themeable);
157 }
158
159 #[test]
160 fn to_json_carries_every_flag() {
161 let j = FacetCaps::NONE.scalable().themeable().editable().to_json();
162 assert_eq!(j["scalable"], true);
163 assert_eq!(j["themeable"], true);
164 assert_eq!(j["editable"], true);
165 assert_eq!(j["copyable"], false);
166 assert_eq!(j.as_object().unwrap().len(), 9);
168 }
169}