immigrant_schema/
attribute.rs1#[derive(Clone, Debug)]
2pub enum AttributeValue {
3 Unset,
5 Set,
7 String(String),
8}
9impl TryFrom<AttributeValue> for bool {
10 type Error = &'static str;
11
12 fn try_from(value: AttributeValue) -> Result<Self, Self::Error> {
13 Ok(match value {
14 AttributeValue::Unset => false,
15 AttributeValue::Set => true,
16 AttributeValue::String(_) => return Err("expected boolean, got string"),
17 })
18 }
19}
20impl TryFrom<AttributeValue> for String {
21 type Error = &'static str;
22
23 fn try_from(value: AttributeValue) -> Result<Self, Self::Error> {
24 Ok(match value {
25 AttributeValue::Unset => return Err("missing string attribute"),
26 AttributeValue::Set => return Err("missing attribute value"),
27 AttributeValue::String(s) => s,
28 })
29 }
30}
31
32#[derive(Debug, Clone)]
33pub struct AttributeField {
34 pub key: String,
35 pub value: AttributeValue,
36}
37
38#[derive(Debug, Clone)]
39pub struct Attribute {
40 pub name: String,
41 pub fields: Vec<AttributeField>,
42}
43
44pub struct DuplicateAttributeError;
45impl From<DuplicateAttributeError> for &'static str {
46 fn from(_value: DuplicateAttributeError) -> Self {
47 "duplicate attribute"
48 }
49}
50
51#[derive(Debug, Clone)]
52pub struct AttributeList(pub Vec<Attribute>);
53impl AttributeList {
54 pub fn iter_fields(&self, attre: &str, fielde: &str, mut cb: impl FnMut(&AttributeValue)) {
55 for attr in &self.0 {
56 if attr.name != attre {
57 continue;
58 }
59 for field in &attr.fields {
60 if field.key != fielde {
61 continue;
62 }
63 cb(&field.value);
64 }
65 }
66 }
67 pub fn get_multi<T>(&self, attre: &str, fielde: &str) -> Result<Vec<T>, T::Error>
68 where
69 T: TryFrom<AttributeValue>,
70 {
71 let mut value = Vec::new();
72 self.iter_fields(attre, fielde, |v| value.push(v.clone()));
73 let mut parsed = Vec::new();
74 for v in value {
75 parsed.push(T::try_from(v)?);
76 }
77 Ok(parsed)
78 }
79 pub fn try_get_single<T>(&self, attre: &str, fielde: &str) -> Result<Option<T>, T::Error>
80 where
81 T: TryFrom<AttributeValue>,
82 T::Error: From<DuplicateAttributeError>,
83 {
84 let v = self.get_multi::<T>(attre, fielde)?;
85 if v.len() > 1 {
86 return Err(DuplicateAttributeError.into());
87 }
88 Ok(v.into_iter().next())
89 }
90 pub fn get_single<T>(&self, attre: &str, fielde: &str) -> Result<T, T::Error>
91 where
92 T: TryFrom<AttributeValue>,
93 T::Error: From<DuplicateAttributeError>,
94 {
95 let v = self.get_multi::<T>(attre, fielde)?;
96 if v.len() > 1 {
97 return Err(DuplicateAttributeError.into());
98 }
99 match v.into_iter().next() { Some(v) => {
100 Ok(v)
101 } _ => {
102 T::try_from(AttributeValue::Unset)
103 }}
104 }
105}