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(
119            self.set
120                .iter()
121                .cloned()
122                .map(|_| PartialValue::PrivateBinary),
123        )
124    }
125
126    fn to_value_iter(&self) -> Box<dyn Iterator<Item = Value> + '_> {
127        Box::new(self.set.iter().cloned().map(Value::PrivateBinary))
128    }
129
130    fn equal(&self, other: &ValueSet) -> bool {
131        if let Some(other) = other.as_private_binary_set() {
132            &self.set == other
133        } else {
134            debug_assert!(false);
135            false
136        }
137    }
138
139    fn merge(&mut self, other: &ValueSet) -> Result<(), OperationError> {
140        if let Some(b) = other.as_private_binary_set() {
141            mergesets!(self.set, b)
142        } else {
143            debug_assert!(false);
144            Err(OperationError::InvalidValueState)
145        }
146    }
147
148    fn to_private_binary_single(&self) -> Option<&[u8]> {
149        if self.set.len() == 1 {
150            self.set.iter().map(|b| b.as_slice()).take(1).next()
151        } else {
152            None
153        }
154    }
155
156    fn as_private_binary_set(&self) -> Option<&SmolSet<[Vec<u8>; 1]>> {
157        Some(&self.set)
158    }
159}
160
161#[derive(Debug, Clone)]
162pub struct ValueSetPublicBinary {
163    map: BTreeMap<String, Vec<u8>>,
164}
165
166impl ValueSetPublicBinary {
167    pub fn new(t: String, b: Vec<u8>) -> Box<Self> {
168        let mut map = BTreeMap::new();
169        map.insert(t, b);
170        Box::new(ValueSetPublicBinary { map })
171    }
172
173    pub fn push(&mut self, t: String, b: Vec<u8>) -> bool {
174        self.map.insert(t, b).is_none()
175    }
176
177    pub fn from_dbvs2(data: Vec<(String, Vec<u8>)>) -> Result<ValueSet, OperationError> {
178        let map = data.into_iter().collect();
179        Ok(Box::new(ValueSetPublicBinary { map }))
180    }
181
182    // We need to allow this, because rust doesn't allow us to impl FromIterator on foreign
183    // types, and tuples are always foreign.
184    #[allow(clippy::should_implement_trait)]
185    pub fn from_iter<T>(iter: T) -> Option<Box<ValueSetPublicBinary>>
186    where
187        T: IntoIterator<Item = (String, Vec<u8>)>,
188    {
189        let map = iter.into_iter().collect();
190        Some(Box::new(ValueSetPublicBinary { map }))
191    }
192}
193
194impl ValueSetT for ValueSetPublicBinary {
195    fn insert_checked(&mut self, value: Value) -> Result<bool, OperationError> {
196        match value {
197            Value::PublicBinary(t, b) => {
198                if let BTreeEntry::Vacant(e) = self.map.entry(t) {
199                    e.insert(b);
200                    Ok(true)
201                } else {
202                    Ok(false)
203                }
204            }
205            _ => Err(OperationError::InvalidValueState),
206        }
207    }
208
209    fn clear(&mut self) {
210        self.map.clear();
211    }
212
213    fn remove(&mut self, pv: &PartialValue, _cid: &Cid) -> bool {
214        match pv {
215            PartialValue::PublicBinary(t) => self.map.remove(t.as_str()).is_some(),
216            _ => false,
217        }
218    }
219
220    fn contains(&self, pv: &PartialValue) -> bool {
221        match pv {
222            PartialValue::PublicBinary(t) => self.map.contains_key(t.as_str()),
223            _ => false,
224        }
225    }
226
227    fn substring(&self, _pv: &PartialValue) -> bool {
228        false
229    }
230
231    fn startswith(&self, _pv: &PartialValue) -> bool {
232        false
233    }
234
235    fn endswith(&self, _pv: &PartialValue) -> bool {
236        false
237    }
238
239    fn lessthan(&self, _pv: &PartialValue) -> bool {
240        false
241    }
242
243    fn len(&self) -> usize {
244        self.map.len()
245    }
246
247    fn generate_idx_eq_keys(&self) -> Vec<String> {
248        self.map.keys().cloned().collect()
249    }
250
251    fn generate_idx_sub_keys(&self) -> Vec<String> {
252        let lower: Vec<_> = self.map.keys().map(|s| s.to_lowercase()).collect();
253        let mut trigraphs: Vec<_> = lower.iter().flat_map(|v| trigraph_iter(v)).collect();
254
255        trigraphs.sort_unstable();
256        trigraphs.dedup();
257
258        trigraphs.into_iter().map(String::from).collect()
259    }
260
261    fn syntax(&self) -> SyntaxType {
262        // Apparently I never actually implemented this type in ... anything?
263        // We should probably clean up syntax soon .....
264        //
265        // SyntaxType::PublicBinary
266        unreachable!()
267    }
268
269    fn validate(&self, _schema_attr: &SchemaAttribute) -> bool {
270        self.map
271            .iter()
272            .all(|(s, _)| Value::validate_str_escapes(s) && Value::validate_singleline(s))
273    }
274
275    fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
276        Box::new(self.map.keys().cloned())
277    }
278
279    fn to_scim_value(&self) -> Option<ScimResolveStatus> {
280        Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
281            self.map
282                .iter()
283                .map(|(tag, bin)| ScimBinary {
284                    label: tag.clone(),
285                    value: bin.clone(),
286                })
287                .collect::<Vec<_>>(),
288        )))
289    }
290
291    fn to_db_valueset_v2(&self) -> DbValueSetV2 {
292        DbValueSetV2::PublicBinary(
293            self.map
294                .iter()
295                .map(|(tag, bin)| (tag.clone(), bin.clone()))
296                .collect(),
297        )
298    }
299
300    fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = PartialValue> + '_> {
301        Box::new(self.map.keys().cloned().map(PartialValue::PublicBinary))
302    }
303
304    fn to_value_iter(&self) -> Box<dyn Iterator<Item = Value> + '_> {
305        Box::new(
306            self.map
307                .iter()
308                .map(|(t, b)| Value::PublicBinary(t.clone(), b.clone())),
309        )
310    }
311
312    fn equal(&self, other: &ValueSet) -> bool {
313        if let Some(other) = other.as_publicbinary_map() {
314            &self.map == other
315        } else {
316            debug_assert!(false);
317            false
318        }
319    }
320
321    fn merge(&mut self, other: &ValueSet) -> Result<(), OperationError> {
322        if let Some(b) = other.as_publicbinary_map() {
323            mergemaps!(self.map, b)
324        } else {
325            debug_assert!(false);
326            Err(OperationError::InvalidValueState)
327        }
328    }
329
330    fn as_publicbinary_map(&self) -> Option<&BTreeMap<String, Vec<u8>>> {
331        Some(&self.map)
332    }
333}
334
335#[cfg(test)]
336mod tests {
337    use super::ValueSetPrivateBinary;
338    use crate::prelude::ValueSet;
339
340    #[test]
341    fn test_scim_private_binary() {
342        let vs: ValueSet = ValueSetPrivateBinary::new(vec![0x00]);
343
344        assert!(vs.to_scim_value().is_none());
345    }
346}