kanidmd_lib/valueset/
hexstring.rs
1use crate::prelude::*;
2use crate::schema::SchemaAttribute;
3use crate::valueset::ScimResolveStatus;
4use crate::valueset::{DbValueSetV2, ValueSet};
5
6use std::collections::BTreeSet;
7
8#[derive(Debug, Clone)]
9pub struct ValueSetHexString {
10 set: BTreeSet<String>,
11}
12
13impl ValueSetHexString {
14 pub fn new(s: String) -> Box<Self> {
15 let mut set = BTreeSet::new();
16 set.insert(s);
17 Box::new(ValueSetHexString { set })
18 }
19
20 pub fn push(&mut self, s: &str) -> bool {
21 self.set.insert(s.to_lowercase())
22 }
23
24 pub fn from_dbvs2(data: Vec<String>) -> Result<ValueSet, OperationError> {
25 let set = data.into_iter().collect();
26 Ok(Box::new(ValueSetHexString { set }))
27 }
28
29 #[allow(clippy::should_implement_trait)]
32 pub fn from_iter<'a, T>(iter: T) -> Option<Box<Self>>
33 where
34 T: IntoIterator<Item = &'a str>,
35 {
36 let set = iter.into_iter().map(str::to_string).collect();
37 Some(Box::new(ValueSetHexString { set }))
38 }
39}
40
41impl ValueSetT for ValueSetHexString {
42 fn insert_checked(&mut self, value: Value) -> Result<bool, OperationError> {
43 match value {
44 Value::HexString(s) => Ok(self.set.insert(s)),
45 _ => {
46 debug_assert!(false);
47 Err(OperationError::InvalidValueState)
48 }
49 }
50 }
51
52 fn clear(&mut self) {
53 self.set.clear();
54 }
55
56 fn remove(&mut self, pv: &PartialValue, _cid: &Cid) -> bool {
57 match pv {
58 PartialValue::HexString(s) => self.set.remove(s),
59 _ => {
60 debug_assert!(false);
61 true
62 }
63 }
64 }
65
66 fn contains(&self, pv: &PartialValue) -> bool {
67 match pv {
68 PartialValue::HexString(s) => self.set.contains(s.as_str()),
69 _ => false,
70 }
71 }
72
73 fn substring(&self, pv: &PartialValue) -> bool {
74 match pv {
75 PartialValue::HexString(s2) => self.set.iter().any(|s1| s1.contains(s2)),
76 _ => {
77 debug_assert!(false);
78 false
79 }
80 }
81 }
82
83 fn startswith(&self, pv: &PartialValue) -> bool {
84 match pv {
85 PartialValue::HexString(s2) => self.set.iter().any(|s1| s1.starts_with(s2)),
86 _ => {
87 debug_assert!(false);
88 false
89 }
90 }
91 }
92
93 fn endswith(&self, pv: &PartialValue) -> bool {
94 match pv {
95 PartialValue::HexString(s2) => self.set.iter().any(|s1| s1.ends_with(s2)),
96 _ => {
97 debug_assert!(false);
98 false
99 }
100 }
101 }
102
103 fn lessthan(&self, _pv: &PartialValue) -> bool {
104 false
105 }
106
107 fn len(&self) -> usize {
108 self.set.len()
109 }
110
111 fn generate_idx_eq_keys(&self) -> Vec<String> {
112 self.set.iter().cloned().collect()
113 }
114
115 fn syntax(&self) -> SyntaxType {
116 SyntaxType::HexString
117 }
118
119 fn validate(&self, _schema_attr: &SchemaAttribute) -> bool {
120 self.set.iter().all(|s| {
121 Value::validate_str_escapes(s.as_str())
122 && Value::validate_singleline(s.as_str())
123 && Value::validate_hexstr(s.as_str())
124 })
125 }
126
127 fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
128 Box::new(self.set.iter().cloned())
129 }
130
131 fn to_scim_value(&self) -> Option<ScimResolveStatus> {
132 let mut iter = self.set.iter().cloned();
133 if self.len() == 1 {
134 let v = iter.next().unwrap_or_default();
135 Some(v.into())
136 } else {
137 let arr = iter.collect::<Vec<_>>();
138 Some(arr.into())
139 }
140 }
141
142 fn to_db_valueset_v2(&self) -> DbValueSetV2 {
143 DbValueSetV2::HexString(self.set.iter().cloned().collect())
144 }
145
146 fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = PartialValue> + '_> {
147 Box::new(self.set.iter().cloned().map(PartialValue::HexString))
148 }
149
150 fn to_value_iter(&self) -> Box<dyn Iterator<Item = Value> + '_> {
151 Box::new(self.set.iter().cloned().map(Value::HexString))
152 }
153
154 fn equal(&self, other: &ValueSet) -> bool {
155 if let Some(other) = other.as_hexstring_set() {
156 &self.set == other
157 } else {
158 debug_assert!(false);
159 false
160 }
161 }
162
163 fn merge(&mut self, other: &ValueSet) -> Result<(), OperationError> {
164 if let Some(b) = other.as_hexstring_set() {
165 mergesets!(self.set, b)
166 } else {
167 debug_assert!(false);
168 Err(OperationError::InvalidValueState)
169 }
170 }
171
172 fn as_hexstring_set(&self) -> Option<&BTreeSet<String>> {
173 Some(&self.set)
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::ValueSetHexString;
180 use crate::prelude::ValueSet;
181
182 #[test]
183 fn test_scim_hexstring() {
184 let vs: ValueSet =
185 ValueSetHexString::new("D68475C760A7A0F6A924C28F095573A967F600D6".to_string());
186 crate::valueset::scim_json_reflexive(&vs, r#""D68475C760A7A0F6A924C28F095573A967F600D6""#);
187 }
188}