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