ferroui_base/utilities/
value_single_or_list.rs1pub struct ValueSingleOrList<T> {
6 is_single_set: bool,
7 single: Option<T>,
8 list: Option<Vec<T>>,
9}
10
11impl<T> Default for ValueSingleOrList<T> {
12 fn default() -> Self {
13 Self { is_single_set: false, single: None, list: None }
14 }
15}
16
17impl<T: PartialEq> ValueSingleOrList<T> {
18 pub fn single(&self) -> Option<&T> {
20 self.single.as_ref()
21 }
22
23 pub fn list(&self) -> Option<&Vec<T>> {
25 self.list.as_ref()
26 }
27
28 pub fn has_list(&self) -> bool {
30 self.list.is_some()
31 }
32
33 pub fn is_single(&self) -> bool {
35 self.list.is_none() && self.is_single_set
36 }
37
38 pub fn add(&mut self, value: T) {
40 if self.list.is_some() {
41 if let Some(list) = &mut self.list {
42 list.push(value);
43 }
44 } else if !self.is_single_set {
45 self.single = Some(value);
46
47 self.is_single_set = true;
48 } else {
49 let mut list = Vec::new();
50
51 if let Some(single) = self.single.take() {
52 list.push(single);
53 }
54 list.push(value);
55
56 self.list = Some(list);
57 }
58 }
59
60 pub fn remove(&mut self, value: &T) -> bool {
62 if let Some(list) = &mut self.list {
63 return match list.iter().position(|item| item == value) {
64 Some(index) => {
65 list.remove(index);
66 true
67 }
68 None => false,
69 };
70 }
71
72 if !self.is_single_set {
73 return false;
74 }
75
76 if self.single.as_ref() == Some(value) {
77 self.single = None;
78
79 self.is_single_set = false;
80
81 return true;
82 }
83
84 false
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
92
93 #[test]
94 fn switches_from_a_single_value_to_a_list() {
95 let mut target = ValueSingleOrList::<i32>::default();
96 assert!(!target.is_single());
97 assert!(!target.has_list());
98
99 target.add(1);
100 assert!(target.is_single());
101 assert_eq!(Some(&1), target.single());
102
103 target.add(2);
104 assert!(!target.is_single());
105 assert!(target.has_list());
106 assert_eq!(None, target.single());
107 assert_eq!(Some(&vec![1, 2]), target.list());
108
109 assert!(target.remove(&1));
110 assert!(!target.remove(&1));
111 assert!(target.has_list());
112 assert_eq!(Some(&vec![2]), target.list());
113 }
114
115 #[test]
116 fn removes_the_single_value() {
117 let mut target = ValueSingleOrList::<i32>::default();
118 assert!(!target.remove(&1));
119
120 target.add(1);
121 assert!(!target.remove(&2));
122 assert!(target.remove(&1));
123 assert!(!target.is_single());
124 assert!(!target.remove(&1));
125 }
126}