kanidmd_lib/valueset/
binary.rs

1use crate::prelude::*;
2use crate::schema::SchemaAttribute;
3use crate::utils::trigraph_iter;
4use crate::valueset::ScimResolveStatus;
5use crate::valueset::{DbValueSetV2, ValueSet};
6use base64urlsafedata::Base64UrlSafeData;
7use kanidm_proto::scim_v1::server::ScimBinary;
8use smolset::SmolSet;
9use std::collections::btree_map::Entry as BTreeEntry;
10use std::collections::BTreeMap;
11
12#[derive(Debug, Clone)]
13pub struct ValueSetPrivateBinary {
14    set: SmolSet<[Vec<u8>; 1]>,
15}
16
17impl ValueSetPrivateBinary {
18    pub fn new(b: Vec<u8>) -> Box<Self> {
19        let mut set = SmolSet::new();
20        set.insert(b);
21        Box::new(ValueSetPrivateBinary { set })
22    }
23
24    pub fn push(&mut self, b: Vec<u8>) -> bool {
25        self.set.insert(b)
26    }
27
28    pub fn from_dbvs2(data: Vec<Vec<u8>>) -> Result<ValueSet, OperationError> {
29        let set = data.into_iter().collect();
30        Ok(Box::new(ValueSetPrivateBinary { set }))
31    }
32
33    pub fn from_repl_v1(data: &[Base64UrlSafeData]) -> Result<ValueSet, OperationError> {
34        let set = data.iter().map(|b| b.to_vec()).collect();
35        Ok(Box::new(ValueSetPrivateBinary { set }))
36    }
37
38    // We need to allow this, because rust doesn't allow us to impl FromIterator on foreign
39    // types, and vec is foreign
40    #[allow(clippy::should_implement_trait)]
41    pub fn from_iter<T>(iter: T) -> Option<Box<ValueSetPrivateBinary>>
42    where
43        T: IntoIterator<Item = Vec<u8>>,
44    {
45        let set = iter.into_iter().collect();
46        Some(Box::new(ValueSetPrivateBinary { set }))
47    }
48}
49
50impl ValueSetT for ValueSetPrivateBinary {
51    fn insert_checked(&mut self, value: Value) -> Result<bool, OperationError> {
52        match value {
53            Value::PrivateBinary(u) => Ok(self.set.insert(u)),
54            _ => {
55                debug_assert!(false);
56                Err(OperationError::InvalidValueState)
57            }
58        }
59    }
60
61    fn clear(&mut self) {
62        self.set.clear();
63    }
64
65    fn remove(&mut self, _pv: &PartialValue, _cid: &Cid) -> bool {
66        true
67    }
68
69    fn contains(&self, _pv: &PartialValue) -> bool {
70        false
71    }
72
73    fn substring(&self, _pv: &PartialValue) -> bool {
74        false
75    }
76
77    fn startswith(&self, _pv: &PartialValue) -> bool {
78        false
79    }
80
81    fn endswith(&self, _pv: &PartialValue) -> bool {
82        false
83    }
84
85    fn lessthan(&self, _pv: &PartialValue) -> bool {
86        false
87    }
88
89    fn len(&self) -> usize {
90        self.set.len()
91    }
92
93    fn generate_idx_eq_keys(&self) -> Vec<String> {
94        Vec::with_capacity(0)
95    }
96
97    fn syntax(&self) -> SyntaxType {
98        SyntaxType::PrivateBinary
99    }
100
101    fn validate(&self, _schema_attr: &SchemaAttribute) -> bool {
102        true
103    }
104
105    fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
106        Box::new(self.set.iter().map(|_| "private_binary".to_string()))
107    }
108
109    fn to_scim_value(&self) -> Option<ScimResolveStatus> {
110        None
111    }
112
113    fn to_db_valueset_v2(&self) -> DbValueSetV2 {
114        DbValueSetV2::PrivateBinary(self.set.iter().cloned().collect())
115    }
116
117    fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = PartialValue> + '_> {
118        Box::new(self.set.iter().map(|_| PartialValue::PrivateBinary))
119    }
120
121    fn to_value_iter(&self) -> Box<dyn Iterator<Item = Value> + '_> {
122        Box::new(self.set.iter().cloned().map(Value::PrivateBinary))
123    }
124
125    fn equal(&self, other: &ValueSet) -> bool {
126        if let Some(other) = other.as_private_binary_set() {
127            &self.set == other
128        } else {
129            debug_assert!(false);
130            false
131        }
132    }
133
134    fn merge(&mut self, other: &ValueSet) -> Result<(), OperationError> {
135        if let Some(b) = other.as_private_binary_set() {
136            mergesets!(self.set, b)
137        } else {
138            debug_assert!(false);
139            Err(OperationError::InvalidValueState)
140        }
141    }
142
143    fn to_private_binary_single(&self) -> Option<&[u8]> {
144        if self.set.len() == 1 {
145            self.set.iter().map(|b| b.as_slice()).take(1).next()
146        } else {
147            None
148        }
149    }
150
151    fn as_private_binary_set(&self) -> Option<&SmolSet<[Vec<u8>; 1]>> {
152        Some(&self.set)
153    }
154}
155
156#[derive(Debug, Clone)]
157pub struct ValueSetPublicBinary {
158    map: BTreeMap<String, Vec<u8>>,
159}
160
161impl ValueSetPublicBinary {
162    pub fn new(t: String, b: Vec<u8>) -> Box<Self> {
163        let mut map = BTreeMap::new();
164        map.insert(t, b);
165        Box::new(ValueSetPublicBinary { map })
166    }
167
168    pub fn push(&mut self, t: String, b: Vec<u8>) -> bool {
169        self.map.insert(t, b).is_none()
170    }
171
172    pub fn from_dbvs2(data: Vec<(String, Vec<u8>)>) -> Result<ValueSet, OperationError> {
173        let map = data.into_iter().collect();
174        Ok(Box::new(ValueSetPublicBinary { map }))
175    }
176
177    // We need to allow this, because rust doesn't allow us to impl FromIterator on foreign
178    // types, and tuples are always foreign.
179    #[allow(clippy::should_implement_trait)]
180    pub fn from_iter<T>(iter: T) -> Option<Box<ValueSetPublicBinary>>
181    where
182        T: IntoIterator<Item = (String, Vec<u8>)>,
183    {
184        let map = iter.into_iter().collect();
185        Some(Box::new(ValueSetPublicBinary { map }))
186    }
187}
188
189impl ValueSetT for ValueSetPublicBinary {
190    fn insert_checked(&mut self, value: Value) -> Result<bool, OperationError> {
191        match value {
192            Value::PublicBinary(t, b) => {
193                if let BTreeEntry::Vacant(e) = self.map.entry(t) {
194                    e.insert(b);
195                    Ok(true)
196                } else {
197                    Ok(false)
198                }
199            }
200            _ => Err(OperationError::InvalidValueState),
201        }
202    }
203
204    fn clear(&mut self) {
205        self.map.clear();
206    }
207
208    fn remove(&mut self, pv: &PartialValue, _cid: &Cid) -> bool {
209        match pv {
210            PartialValue::PublicBinary(t) => self.map.remove(t.as_str()).is_some(),
211            _ => false,
212        }
213    }
214
215    fn contains(&self, pv: &PartialValue) -> bool {
216        match pv {
217            PartialValue::PublicBinary(t) => self.map.contains_key(t.as_str()),
218            _ => false,
219        }
220    }
221
222    fn substring(&self, _pv: &PartialValue) -> bool {
223        false
224    }
225
226    fn startswith(&self, _pv: &PartialValue) -> bool {
227        false
228    }
229
230    fn endswith(&self, _pv: &PartialValue) -> bool {
231        false
232    }
233
234    fn lessthan(&self, _pv: &PartialValue) -> bool {
235        false
236    }
237
238    fn len(&self) -> usize {
239        self.map.len()
240    }
241
242    fn generate_idx_eq_keys(&self) -> Vec<String> {
243        self.map.keys().cloned().collect()
244    }
245
246    fn generate_idx_sub_keys(&self) -> Vec<String> {
247        let lower: Vec<_> = self.map.keys().map(|s| s.to_lowercase()).collect();
248        let mut trigraphs: Vec<_> = lower.iter().flat_map(|v| trigraph_iter(v)).collect();
249
250        trigraphs.sort_unstable();
251        trigraphs.dedup();
252
253        trigraphs.into_iter().map(String::from).collect()
254    }
255
256    fn syntax(&self) -> SyntaxType {
257        // Apparently I never actually implemented this type in ... anything?
258        // We should probably clean up syntax soon .....
259        //
260        // SyntaxType::PublicBinary
261        unreachable!()
262    }
263
264    fn validate(&self, _schema_attr: &SchemaAttribute) -> bool {
265        self.map
266            .iter()
267            .all(|(s, _)| Value::validate_str_escapes(s) && Value::validate_singleline(s))
268    }
269
270    fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
271        Box::new(self.map.keys().cloned())
272    }
273
274    fn to_scim_value(&self) -> Option<ScimResolveStatus> {
275        Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
276            self.map
277                .iter()
278                .map(|(tag, bin)| ScimBinary {
279                    label: tag.clone(),
280                    value: bin.clone(),
281                })
282                .collect::<Vec<_>>(),
283        )))
284    }
285
286    fn to_db_valueset_v2(&self) -> DbValueSetV2 {
287        DbValueSetV2::PublicBinary(
288            self.map
289                .iter()
290                .map(|(tag, bin)| (tag.clone(), bin.clone()))
291                .collect(),
292        )
293    }
294
295    fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = PartialValue> + '_> {
296        Box::new(self.map.keys().cloned().map(PartialValue::PublicBinary))
297    }
298
299    fn to_value_iter(&self) -> Box<dyn Iterator<Item = Value> + '_> {
300        Box::new(
301            self.map
302                .iter()
303                .map(|(t, b)| Value::PublicBinary(t.clone(), b.clone())),
304        )
305    }
306
307    fn equal(&self, other: &ValueSet) -> bool {
308        if let Some(other) = other.as_publicbinary_map() {
309            &self.map == other
310        } else {
311            debug_assert!(false);
312            false
313        }
314    }
315
316    fn merge(&mut self, other: &ValueSet) -> Result<(), OperationError> {
317        if let Some(b) = other.as_publicbinary_map() {
318            mergemaps!(self.map, b)
319        } else {
320            debug_assert!(false);
321            Err(OperationError::InvalidValueState)
322        }
323    }
324
325    fn as_publicbinary_map(&self) -> Option<&BTreeMap<String, Vec<u8>>> {
326        Some(&self.map)
327    }
328}
329
330#[cfg(test)]
331mod tests {
332    use super::ValueSetPrivateBinary;
333    use crate::prelude::ValueSet;
334
335    #[test]
336    fn test_scim_private_binary() {
337        let vs: ValueSet = ValueSetPrivateBinary::new(vec![0x00]);
338
339        assert!(vs.to_scim_value().is_none());
340    }
341}