Skip to main content

swf_core/models/
map.rs

1use serde::de::{SeqAccess, Visitor};
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::collections::HashMap;
4use std::fmt;
5use std::hash::Hash;
6
7/// Represents an ordered key/value map array.
8///
9/// Internally uses `Vec<(K, V)>` for efficient storage, but serializes to/from
10/// the Serverless Workflow DSL format: `[{"key1": "value1"}, {"key2": "value2"}]`.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct Map<TKey, TValue>
13where
14    TKey: Eq + Hash + Clone + PartialEq,
15    TValue: Clone + PartialEq,
16{
17    /// The ordered entries as (key, value) pairs
18    pub entries: Vec<(TKey, TValue)>,
19}
20
21impl<TKey, TValue> Default for Map<TKey, TValue>
22where
23    TKey: Eq + Hash + Clone + PartialEq,
24    TValue: Clone + PartialEq,
25{
26    fn default() -> Self {
27        Map {
28            entries: Vec::new(),
29        }
30    }
31}
32
33impl<TKey, TValue> Map<TKey, TValue>
34where
35    TKey: Eq + Hash + Clone + PartialEq,
36    TValue: Clone + PartialEq,
37{
38    /// Initializes a new map
39    pub fn new() -> Self {
40        Self::default()
41    }
42
43    /// Initializes a new map with the provided entries
44    pub fn from(entries: Vec<(TKey, TValue)>) -> Self {
45        Map { entries }
46    }
47
48    /// Adds the specified entry
49    pub fn add(&mut self, key: TKey, value: TValue) {
50        self.entries.push((key, value));
51    }
52
53    /// Gets the number of entries in the map
54    pub fn len(&self) -> usize {
55        self.entries.len()
56    }
57
58    /// Checks if the map is empty
59    pub fn is_empty(&self) -> bool {
60        self.entries.is_empty()
61    }
62
63    /// Checks if the map contains an entry with the specified key
64    pub fn contains_key(&self, key: &TKey) -> bool {
65        self.entries.iter().any(|(k, _)| k == key)
66    }
67
68    /// Gets a reference to the value associated with the specified key
69    pub fn get(&self, key: &TKey) -> Option<&TValue> {
70        self.entries.iter().find(|(k, _)| k == key).map(|(_, v)| v)
71    }
72}
73
74// Custom serialization: Vec<(K,V)> -> array of single-key objects [{k: v}, ...]
75impl<TKey, TValue> Serialize for Map<TKey, TValue>
76where
77    TKey: Eq + Hash + Clone + Serialize + PartialEq,
78    TValue: Clone + Serialize + PartialEq,
79{
80    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
81        use serde::ser::SerializeSeq;
82
83        let mut seq = serializer.serialize_seq(Some(self.entries.len()))?;
84        for (key, value) in &self.entries {
85            let mut hm = HashMap::new();
86            hm.insert(key, value);
87            seq.serialize_element(&hm)?;
88        }
89        seq.end()
90    }
91}
92
93// Custom deserialization: array of single-key objects -> Vec<(K,V)>
94impl<'de, TKey, TValue> Deserialize<'de> for Map<TKey, TValue>
95where
96    TKey: Eq + Hash + Clone + Deserialize<'de> + PartialEq,
97    TValue: Clone + Deserialize<'de> + PartialEq,
98{
99    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
100        struct MapVisitor<TKey, TValue> {
101            _phantom: std::marker::PhantomData<(TKey, TValue)>,
102        }
103
104        impl<'de, TKey, TValue> Visitor<'de> for MapVisitor<TKey, TValue>
105        where
106            TKey: Eq + Hash + Clone + Deserialize<'de> + PartialEq,
107            TValue: Clone + Deserialize<'de> + PartialEq,
108        {
109            type Value = Map<TKey, TValue>;
110
111            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
112                formatter.write_str("an array of single-key objects")
113            }
114
115            fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
116                let mut entries = Vec::new();
117                while let Some(hm) = seq.next_element::<HashMap<TKey, TValue>>()? {
118                    for (k, v) in hm {
119                        entries.push((k, v));
120                    }
121                }
122                Ok(Map { entries })
123            }
124        }
125
126        deserializer.deserialize_seq(MapVisitor {
127            _phantom: std::marker::PhantomData,
128        })
129    }
130}
131
132#[cfg(test)]
133mod tests {
134    use super::*;
135
136    #[test]
137    fn test_map_new() {
138        let map: Map<String, String> = Map::new();
139        assert!(map.is_empty());
140        assert_eq!(map.len(), 0);
141    }
142
143    #[test]
144    fn test_map_default() {
145        let map: Map<String, String> = Map::default();
146        assert!(map.is_empty());
147    }
148
149    #[test]
150    fn test_map_from_entries() {
151        let map: Map<String, String> = Map::from(vec![
152            ("key1".to_string(), "value1".to_string()),
153            ("key2".to_string(), "value2".to_string()),
154        ]);
155        assert_eq!(map.len(), 2);
156        assert_eq!(map.get(&"key1".to_string()), Some(&"value1".to_string()));
157        assert_eq!(map.get(&"key2".to_string()), Some(&"value2".to_string()));
158    }
159
160    #[test]
161    fn test_map_add() {
162        let mut map: Map<String, String> = Map::new();
163        map.add("key1".to_string(), "value1".to_string());
164        map.add("key2".to_string(), "value2".to_string());
165        assert_eq!(map.len(), 2);
166        assert_eq!(map.get(&"key1".to_string()), Some(&"value1".to_string()));
167    }
168
169    #[test]
170    fn test_map_contains_key() {
171        let map: Map<String, String> = Map::from(vec![("key1".to_string(), "value1".to_string())]);
172        assert!(map.contains_key(&"key1".to_string()));
173        assert!(!map.contains_key(&"key2".to_string()));
174    }
175
176    #[test]
177    fn test_map_get_missing_key() {
178        let map: Map<String, String> = Map::from(vec![("key1".to_string(), "value1".to_string())]);
179        assert!(map.get(&"nonexistent".to_string()).is_none());
180    }
181
182    #[test]
183    fn test_map_serde_roundtrip() {
184        let map: Map<String, String> = Map::from(vec![
185            ("task1".to_string(), "value1".to_string()),
186            ("task2".to_string(), "value2".to_string()),
187        ]);
188        let json = serde_json::to_string(&map).unwrap();
189        let deserialized: Map<String, String> = serde_json::from_str(&json).unwrap();
190        assert_eq!(map, deserialized);
191    }
192
193    #[test]
194    fn test_map_serializes_to_array_of_single_key_objects() {
195        let map: Map<String, i32> = Map::from(vec![("a".to_string(), 1), ("b".to_string(), 2)]);
196        let json = serde_json::to_string(&map).unwrap();
197        assert_eq!(json, r#"[{"a":1},{"b":2}]"#);
198    }
199
200    #[test]
201    fn test_map_deserializes_from_array_of_single_key_objects() {
202        let json = r#"[{"a":1},{"b":2}]"#;
203        let map: Map<String, i32> = serde_json::from_str(json).unwrap();
204        assert_eq!(map.len(), 2);
205        assert_eq!(map.get(&"a".to_string()), Some(&1));
206        assert_eq!(map.get(&"b".to_string()), Some(&2));
207    }
208}