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