Skip to main content

auditor/domain/
meta.rs

1// Copyright 2021-2022 AUDITOR developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use std::{cmp::Ordering, collections::HashMap};
9
10use serde::{Deserialize, Serialize};
11
12use super::ValidName;
13
14#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)]
15pub struct ValidMeta(pub HashMap<ValidName, Vec<ValidName>>);
16
17impl ValidMeta {
18    pub fn to_vec(&self) -> Vec<(String, Vec<String>)> {
19        self.0
20            .iter()
21            .map(|(k, v)| {
22                (
23                    k.as_ref().to_string(),
24                    v.iter().map(|v| v.as_ref().to_string()).collect(),
25                )
26            })
27            .collect::<Vec<_>>()
28    }
29}
30
31impl<T: AsRef<str>> TryFrom<HashMap<T, Vec<T>>> for ValidMeta {
32    type Error = anyhow::Error;
33
34    fn try_from(m: HashMap<T, Vec<T>>) -> Result<Self, Self::Error> {
35        Ok(Self(
36            m.into_iter()
37                .map(|(k, v)| -> Result<_, Self::Error> {
38                    Ok((
39                        ValidName::parse(k.as_ref().to_string())?,
40                        v.iter()
41                            .map(|v| -> Result<_, Self::Error> {
42                                Ok(ValidName::parse(v.as_ref().to_string())?)
43                            })
44                            .collect::<Result<Vec<ValidName>, Self::Error>>()?,
45                    ))
46                })
47                .collect::<Result<_, Self::Error>>()?,
48        ))
49    }
50}
51
52impl TryFrom<Vec<(String, Vec<String>)>> for ValidMeta {
53    type Error = anyhow::Error;
54
55    fn try_from(m: Vec<(String, Vec<String>)>) -> Result<Self, Self::Error> {
56        Ok(Self(
57            m.into_iter()
58                .map(|um| -> Result<_, Self::Error> {
59                    Ok((
60                        ValidName::parse(um.0)?,
61                        um.1.into_iter()
62                            .map(|v| -> Result<_, Self::Error> { Ok(ValidName::parse(v)?) })
63                            .collect::<Result<Vec<ValidName>, Self::Error>>()?,
64                    ))
65                })
66                .collect::<Result<_, Self::Error>>()?,
67        ))
68    }
69}
70
71impl TryFrom<Meta> for ValidMeta {
72    type Error = anyhow::Error;
73
74    fn try_from(m: Meta) -> Result<Self, Self::Error> {
75        Ok(Self(
76            m.0.into_iter()
77                .map(|(key, value)| -> Result<_, Self::Error> {
78                    Ok((
79                        ValidName::parse(key)?,
80                        value
81                            .into_iter()
82                            .map(|v| -> Result<_, Self::Error> { Ok(ValidName::parse(v)?) })
83                            .collect::<Result<Vec<ValidName>, Self::Error>>()?,
84                    ))
85                })
86                .collect::<Result<_, Self::Error>>()?,
87        ))
88    }
89}
90
91/// `Meta` stores a list of key-value pairs of the form `String` -> `Vec<String>`.
92///
93/// # Example
94///
95/// Create a new meta list and insert two key-value pairs:
96///
97/// ```
98/// # use auditor::domain::Meta;
99/// #
100/// let mut meta = Meta::new();
101/// meta.insert("site_id".to_string(), vec!["site1".to_string()]);
102/// meta.insert("features".to_string(), vec!["ssd".to_string(), "gpu".to_string()]);
103/// ```
104#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default, sqlx::FromRow)]
105pub struct Meta(pub HashMap<String, Vec<String>>);
106
107impl Meta {
108    /// Constructor.
109    pub fn new() -> Self {
110        Self(HashMap::new())
111    }
112
113    /// Returns the number of key-value pairs that are stored inside the meta list.
114    pub fn len(&self) -> usize {
115        self.0.len()
116    }
117
118    /// Returns `true` if no information is stored in the meta list.
119    pub fn is_empty(&self) -> bool {
120        self.len() == 0
121    }
122
123    /// Convert to a vector.
124    pub fn to_vec(&self) -> Vec<(String, Vec<String>)> {
125        self.0
126            .iter()
127            .map(|(k, v)| (k.clone(), v.clone()))
128            .collect::<Vec<_>>()
129    }
130
131    /// Insert a new key-value pair.
132    pub fn insert(&mut self, name: String, values: Vec<String>) {
133        self.0.insert(name, values);
134    }
135
136    /// Returns a reference to the value corresponding to the `key`.
137    pub fn get<T: AsRef<str>>(&self, key: T) -> Option<&Vec<String>> {
138        self.0.get(key.as_ref())
139    }
140}
141
142impl From<ValidMeta> for Meta {
143    fn from(m: ValidMeta) -> Self {
144        Self(
145            m.0.into_iter()
146                .map(|(k, v)| {
147                    (
148                        k.as_ref().to_string(),
149                        v.into_iter().map(|v| v.as_ref().to_string()).collect(),
150                    )
151                })
152                .collect(),
153        )
154    }
155}
156
157impl<T: AsRef<str>> TryFrom<HashMap<T, Vec<T>>> for Meta {
158    type Error = anyhow::Error;
159
160    fn try_from(m: HashMap<T, Vec<T>>) -> Result<Self, Self::Error> {
161        Ok(Self(
162            m.into_iter()
163                .map(|(k, v)| -> Result<_, Self::Error> {
164                    Ok((
165                        k.as_ref().to_string(),
166                        v.into_iter()
167                            .map(|v| -> Result<_, Self::Error> { Ok(v.as_ref().to_string()) })
168                            .collect::<Result<Vec<String>, Self::Error>>()?,
169                    ))
170                })
171                .collect::<Result<_, Self::Error>>()?,
172        ))
173    }
174}
175
176impl TryFrom<Vec<(String, Vec<String>)>> for Meta {
177    type Error = anyhow::Error;
178
179    fn try_from(m: Vec<(String, Vec<String>)>) -> Result<Self, Self::Error> {
180        Ok(Self(
181            m.into_iter()
182                .map(|um| -> Result<_, Self::Error> { Ok((um.0.clone(), um.1)) })
183                .collect::<Result<_, Self::Error>>()?,
184        ))
185    }
186}
187
188impl PartialOrd for Meta {
189    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
190        Some(self.cmp(other))
191    }
192}
193
194impl Ord for Meta {
195    fn cmp(&self, _other: &Self) -> Ordering {
196        Ordering::Equal
197    }
198}