updatehub_sdk/api/info/
firmware.rs

1// Copyright (C) 2020 O.S. Systems Sofware LTDA
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use serde::{
6    de::{Deserializer, MapAccess, Visitor},
7    ser::{SerializeMap, Serializer},
8    Deserialize, Serialize,
9};
10use std::{
11    collections::{
12        btree_map::{Entry, Keys},
13        BTreeMap,
14    },
15    fmt,
16    ops::Index,
17    path::PathBuf,
18};
19
20/// Metadata stores the firmware metadata information. It is
21/// organized in multiple fields.
22///
23/// The Metadata is created loading its information from the running
24/// firmware. It uses the `load` method for that.
25#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
26#[serde(deny_unknown_fields)]
27pub struct Metadata {
28    /// Product UID which identifies the firmware on the management system
29    pub product_uid: String,
30    /// Version of firmware
31    pub version: String,
32    /// Hardware where the firmware is running
33    pub hardware: String,
34    /// Path for the pub key being used
35    pub pub_key: Option<PathBuf>,
36    /// Device Identity
37    pub device_identity: MetadataValue,
38    /// Device Attributes
39    pub device_attributes: MetadataValue,
40}
41
42#[derive(Clone, Debug, Default, PartialEq, Eq)]
43pub struct MetadataValue(pub BTreeMap<String, Vec<String>>);
44
45impl MetadataValue {
46    pub fn entry(&mut self, key: String) -> Entry<'_, String, Vec<String>> {
47        self.0.entry(key)
48    }
49
50    pub fn keys(&self) -> Keys<'_, String, Vec<String>> {
51        self.0.keys()
52    }
53
54    pub fn is_empty(&self) -> bool {
55        self.0.len() == 0
56    }
57
58    pub fn len(&self) -> usize {
59        self.0.len()
60    }
61}
62
63impl Serialize for MetadataValue {
64    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65    where
66        S: Serializer,
67    {
68        let mut map = serializer.serialize_map(Some(self.0.len()))?;
69        for (k, v) in &self.0 {
70            if v.len() == 1 {
71                map.serialize_entry(k, &v[0])?;
72            } else {
73                map.serialize_entry(k, v)?;
74            }
75        }
76        map.end()
77    }
78}
79
80impl<'de> Deserialize<'de> for MetadataValue {
81    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82    where
83        D: Deserializer<'de>,
84    {
85        #[derive(Deserialize)]
86        #[serde(untagged)]
87        enum Value {
88            One(String),
89            Many(Vec<String>),
90        }
91
92        impl From<Value> for Vec<String> {
93            fn from(value: Value) -> Self {
94                match value {
95                    Value::One(s) => vec![s],
96                    Value::Many(v) => v,
97                }
98            }
99        }
100
101        struct MetadataValueVisitor;
102
103        impl<'de> Visitor<'de> for MetadataValueVisitor {
104            type Value = MetadataValue;
105
106            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
107                formatter.write_str("tuple struct MetadataValue")
108            }
109
110            fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
111            where
112                M: MapAccess<'de>,
113            {
114                let mut map = MetadataValue::default();
115
116                while let Some((k, v)) = access.next_entry::<_, Value>()? {
117                    map.0.insert(k, v.into());
118                }
119
120                Ok(map)
121            }
122        }
123
124        deserializer.deserialize_map(MetadataValueVisitor)
125    }
126}
127
128impl<'a> Index<&'a str> for MetadataValue {
129    type Output = Vec<String>;
130
131    #[inline]
132    fn index(&self, key: &str) -> &Vec<String> {
133        self.0.get(key).expect("no entry found for key")
134    }
135}