srad_types/
property_set.rs

1use std::collections::HashMap;
2
3use crate::{
4    constants::QUALITY,
5    payload::{self, property_value},
6    quality::Quality,
7    traits, PropertyValue as PropertyValueValue,
8};
9
10#[derive(Debug)]
11struct PropertyValue {
12    value: Option<PropertyValueValue>,
13    datatype: Option<payload::DataType>,
14}
15
16impl From<PropertyValue> for payload::PropertyValue {
17    fn from(value: PropertyValue) -> Self {
18        let mut is_null = None;
19        let mut pvv = None;
20        match value.value {
21            Some(v) => pvv = Some(v.into()),
22            None => is_null = Some(true),
23        }
24        payload::PropertyValue {
25            r#type: value.datatype.map(|x| x as u32),
26            is_null,
27            value: pvv,
28        }
29    }
30}
31
32impl TryFrom<payload::PropertyValue> for PropertyValue {
33    type Error = ();
34
35    fn try_from(payload: payload::PropertyValue) -> Result<Self, Self::Error> {
36        let value = if let Some(value) = payload.value {
37            Some(PropertyValueValue::new(value))
38        } else if let Some(is_null) = payload.is_null {
39            if is_null {
40                None
41            } else {
42                return Err(());
43            }
44        } else {
45            return Err(());
46        };
47
48        let ty = match payload.r#type {
49            Some(v) => Some(v.try_into()?),
50            None => None,
51        };
52        Ok(Self {
53            value,
54            datatype: ty,
55        })
56    }
57}
58
59/// A collection of property values
60#[derive(Debug)]
61pub struct PropertySet(HashMap<String, PropertyValue>);
62
63impl Default for PropertySet {
64    fn default() -> Self {
65        Self::new()
66    }
67}
68
69impl PropertySet {
70    pub fn new_with_quality(quality: Quality) -> Self {
71        let mut pset = PropertySet(HashMap::new());
72        pset.0.insert(
73            QUALITY.to_string(),
74            PropertyValue {
75                value: Some(quality.into()),
76                datatype: Some(payload::DataType::Int32),
77            },
78        );
79        pset
80    }
81
82    pub fn new() -> Self {
83        Self::new_with_quality(Quality::Good)
84    }
85
86    #[allow(clippy::result_unit_err)]
87    pub fn insert<K: Into<String>, V: traits::PropertyValue>(
88        &mut self,
89        k: K,
90        v: Option<V>,
91    ) -> Result<(), ()> {
92        let key = k.into();
93        if key == QUALITY {
94            return Err(());
95        }
96        let pv = PropertyValue {
97            value: v.map(V::into),
98            datatype: Some(V::default_datatype()),
99        };
100        self.0.insert(key, pv);
101        Ok(())
102    }
103}
104
105impl traits::HasDataType for PropertySet {
106    fn supported_datatypes() -> &'static [payload::DataType] {
107        static SUPPORTED_TYPES: [payload::DataType; 1] = [payload::DataType::PropertySet];
108        &SUPPORTED_TYPES
109    }
110}
111
112impl TryFrom<PropertyValueValue> for PropertySet {
113    type Error = ();
114
115    fn try_from(value: PropertyValueValue) -> Result<Self, Self::Error> {
116        let value: payload::property_value::Value = value.into();
117        if let payload::property_value::Value::PropertysetValue(v) = value {
118            Ok(v.try_into()?)
119        } else {
120            Err(())
121        }
122    }
123}
124
125impl From<PropertySet> for PropertyValueValue {
126    fn from(value: PropertySet) -> Self {
127        PropertyValueValue::new(property_value::Value::PropertysetValue(value.into()))
128    }
129}
130
131impl traits::PropertyValue for PropertySet {}
132
133impl From<PropertySet> for payload::PropertySet {
134    fn from(value: PropertySet) -> Self {
135        let len = value.0.len();
136        let mut keys = Vec::with_capacity(len);
137        let mut values: Vec<payload::PropertyValue> = Vec::with_capacity(len);
138        value.0.into_iter().for_each(|(k, v)| {
139            keys.push(k);
140            values.push(v.into());
141        });
142        payload::PropertySet { keys, values }
143    }
144}
145
146impl TryFrom<payload::PropertySet> for PropertySet {
147    type Error = ();
148
149    fn try_from(value: payload::PropertySet) -> Result<Self, Self::Error> {
150        let keys = value.keys;
151        let values = value.values;
152        let len = keys.len();
153        if len != values.len() {
154            return Err(());
155        }
156
157        let mut hashmap: HashMap<String, PropertyValue> = HashMap::with_capacity(len);
158        for (k, v) in keys.into_iter().zip(values) {
159            let value = v.try_into()?;
160            hashmap.insert(k, value);
161        }
162
163        Ok(PropertySet(hashmap))
164    }
165}
166
167type PropertySetList = Vec<PropertySet>;
168
169impl From<PropertySetList> for payload::PropertySetList {
170    fn from(value: PropertySetList) -> Self {
171        let mut out = Vec::with_capacity(value.len());
172        for x in value.into_iter() {
173            out.push(x.into())
174        }
175        payload::PropertySetList { propertyset: out }
176    }
177}
178
179impl TryFrom<payload::PropertySetList> for PropertySetList {
180    type Error = ();
181
182    fn try_from(value: payload::PropertySetList) -> Result<Self, Self::Error> {
183        let mut out = Vec::with_capacity(value.propertyset.len());
184        for x in value.propertyset.into_iter() {
185            out.push(x.try_into()?)
186        }
187        Ok(out)
188    }
189}
190
191impl traits::HasDataType for PropertySetList {
192    fn supported_datatypes() -> &'static [payload::DataType] {
193        static SUPPORTED_TYPES: [payload::DataType; 1] = [payload::DataType::PropertySetList];
194        &SUPPORTED_TYPES
195    }
196}
197
198impl TryFrom<PropertyValueValue> for PropertySetList {
199    type Error = ();
200
201    fn try_from(value: PropertyValueValue) -> Result<Self, Self::Error> {
202        let value: payload::property_value::Value = value.into();
203        if let payload::property_value::Value::PropertysetsValue(v) = value {
204            Ok(v.try_into()?)
205        } else {
206            Err(())
207        }
208    }
209}
210
211impl From<PropertySetList> for PropertyValueValue {
212    fn from(value: PropertySetList) -> Self {
213        PropertyValueValue::new(property_value::Value::PropertysetsValue(value.into()))
214    }
215}
216
217impl traits::PropertyValue for PropertySetList {}