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