svd_rs/
array.rs

1use super::{Description, DimElement, Name};
2use core::ops::{Deref, DerefMut};
3
4/// A single SVD instance or array of instances
5#[derive(Clone, Debug, PartialEq, Eq)]
6pub enum MaybeArray<T> {
7    /// A single instance
8    Single(T),
9    /// An array of instances
10    Array(T, DimElement),
11}
12
13impl<T> Deref for MaybeArray<T> {
14    type Target = T;
15
16    fn deref(&self) -> &T {
17        match self {
18            Self::Single(info) => info,
19            Self::Array(info, _) => info,
20        }
21    }
22}
23
24impl<T> DerefMut for MaybeArray<T> {
25    fn deref_mut(&mut self) -> &mut T {
26        match self {
27            Self::Single(info) => info,
28            Self::Array(info, _) => info,
29        }
30    }
31}
32
33impl<T> MaybeArray<T> {
34    /// Return `true` if instance is single
35    pub const fn is_single(&self) -> bool {
36        matches!(self, Self::Single(_))
37    }
38    /// Return `true` if it is an array
39    pub const fn is_array(&self) -> bool {
40        matches!(self, Self::Array(_, _))
41    }
42}
43
44impl<T> Name for MaybeArray<T>
45where
46    T: Name,
47{
48    fn name(&self) -> &str {
49        T::name(self)
50    }
51}
52
53impl<T> Description for MaybeArray<T>
54where
55    T: Description,
56{
57    fn description(&self) -> Option<&str> {
58        T::description(self)
59    }
60}
61
62/// Return list of names of instances in array
63pub fn names<'a, T: Name>(info: &'a T, dim: &'a DimElement) -> impl Iterator<Item = String> + 'a {
64    let name = info.name();
65    dim.indexes().map(move |i| {
66        dim.dim_array_index
67            .as_ref()
68            .and_then(|dai| {
69                dai.values
70                    .iter()
71                    .find(|e| e.value.map(|v| v.to_string().as_str() == i.deref()) == Some(true))
72            })
73            .map(|n| n.name.clone())
74            .unwrap_or_else(|| name.replace("[%s]", &i).replace("%s", &i))
75    })
76}
77
78/// Return list of descriptions of instances in array
79pub fn descriptions<'a, T: Description>(
80    info: &'a T,
81    dim: &'a DimElement,
82) -> impl Iterator<Item = Option<String>> + 'a {
83    let description = info.description();
84    dim.indexes().map(move |i| {
85        dim.dim_array_index
86            .as_ref()
87            .and_then(|dai| {
88                dai.values
89                    .iter()
90                    .find(|e| e.value.map(|v| v.to_string().as_str() == i.deref()) == Some(true))
91            })
92            .and_then(|n| n.description.clone())
93            .or_else(|| description.map(|d| d.replace("[%s]", &i).replace("%s", &i)))
94    })
95}
96
97#[cfg(feature = "serde")]
98mod ser_de {
99    use super::*;
100    use serde::{Deserialize, Deserializer, Serialize, Serializer};
101
102    #[derive(serde::Serialize)]
103    struct SerArray<'a, T> {
104        #[serde(flatten)]
105        dim: &'a DimElement,
106        #[serde(flatten)]
107        info: &'a T,
108    }
109
110    #[derive(serde::Deserialize)]
111    struct DeserArray<T> {
112        #[serde(flatten, default)]
113        dim: Option<DimElement>,
114        #[serde(flatten)]
115        info: T,
116    }
117
118    impl<T> Serialize for MaybeArray<T>
119    where
120        T: Serialize,
121    {
122        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
123        where
124            S: Serializer,
125        {
126            match self {
127                Self::Single(info) => info.serialize(serializer),
128                Self::Array(info, dim) => SerArray::<T> { dim, info }.serialize(serializer),
129            }
130        }
131    }
132
133    impl<'de, T> Deserialize<'de> for MaybeArray<T>
134    where
135        T: Deserialize<'de>,
136    {
137        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
138        where
139            D: Deserializer<'de>,
140        {
141            let DeserArray { dim, info } = DeserArray::<T>::deserialize(deserializer)?;
142            if let Some(dim) = dim {
143                Ok(Self::Array(info, dim))
144            } else {
145                Ok(Self::Single(info))
146            }
147        }
148    }
149}