mistletoe_api/v1alpha1/
mistpackage.rs

1use indexmap::IndexMap;
2use serde::{Serialize, Deserialize, Serializer, Deserializer};
3
4/// Info about the package that it returns when queried about.
5///
6/// This contains a name and some optional labels.
7#[derive(Clone, PartialEq, Debug)]
8pub struct MistPackage {
9    /// Name of the package.
10    pub name: String,
11
12    /// Package labels.
13    /// 
14    /// These can be whatever the package maintainer decides to attach, though
15    /// there are some labels with significance that Mistletoe can use to provide
16    /// additional information about the package to the end-user, notably
17    /// `mistletoe.dev/group`.
18    pub labels: Option<IndexMap<String, String>>,
19}
20
21#[derive(Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23struct MistPackageLayout {
24    api_version: String,
25    kind: String,
26    metadata: MistPackageLayoutMetadata,
27}
28
29#[derive(Serialize, Deserialize)]
30struct MistPackageLayoutMetadata {
31    name: String,
32    #[serde(default, skip_serializing_if = "Option::is_none")]
33    labels: Option<IndexMap<String, String>>,
34}
35
36impl From<MistPackage> for MistPackageLayout {
37    fn from(mhp: MistPackage) -> MistPackageLayout {
38        MistPackageLayout {
39            api_version: "mistletoe.dev/v1alpha1".to_string(),
40            kind: "MistPackage".to_string(),
41            metadata: MistPackageLayoutMetadata {
42                name: mhp.name,
43                labels: mhp.labels,
44            },
45        }
46    }
47}
48
49impl Into<MistPackage> for MistPackageLayout {
50    fn into(self) -> MistPackage {
51        MistPackage {
52            name: self.metadata.name,
53            labels: self.metadata.labels,
54        }
55    }
56}
57
58impl Serialize for MistPackage {
59    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
60    where
61        S: Serializer
62    {
63        MistPackageLayout::from(self.clone()).serialize(serializer)
64    }
65}
66
67impl<'de> Deserialize<'de> for MistPackage {
68    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69    where
70        D: Deserializer<'de>
71    {
72        let mrl = MistPackageLayout::deserialize(deserializer)?;
73        Ok(mrl.into())
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80    use indoc::indoc;
81
82    #[test]
83    fn test_mistpackage() {
84        let expected_yaml = indoc! {"
85            apiVersion: mistletoe.dev/v1alpha1
86            kind: MistPackage
87            metadata:
88              name: example-nginx
89              labels:
90                mistletoe.dev/group: mistletoe-examples"};
91
92        let mut labels = IndexMap::new();
93        labels.insert("mistletoe.dev/group".to_string(), "mistletoe-examples".to_string());
94
95        let mistpackage = MistPackage {
96            name: "example-nginx".to_string(),
97            labels: Some(labels),
98        };
99
100        let yaml = serde_yaml::to_string(&mistpackage).unwrap();
101        assert_eq!(expected_yaml, yaml, "left:\n{expected_yaml}\nright:\n{expected_yaml}");
102
103        let mistpackage_parsed = serde_yaml::from_str(&yaml).unwrap();
104        assert_eq!(mistpackage, mistpackage_parsed);
105    }
106}