y_octo/doc/types/
map.rs

1use std::{collections::hash_map::Iter, rc::Rc};
2
3use super::*;
4use crate::{
5    JwstCodecResult,
6    doc::{AsInner, Node, Parent, YTypeRef},
7    impl_type,
8};
9
10impl_type!(Map);
11
12pub(crate) trait MapType: AsInner<Inner = YTypeRef> {
13    fn _id(&self) -> Option<Id> {
14        self.as_inner().ty().and_then(|ty| ty.item.get().map(|item| item.id))
15    }
16
17    fn _insert<V: Into<Value>>(&mut self, key: String, value: V) -> JwstCodecResult {
18        if let Some((mut store, mut ty)) = self.as_inner().write() {
19            let left = ty.map.get(&SmolStr::new(&key)).cloned();
20
21            let item = store.create_item(
22                value.into().into(),
23                left.unwrap_or(Somr::none()),
24                Somr::none(),
25                Some(Parent::Type(self.as_inner().clone())),
26                Some(SmolStr::new(key)),
27            );
28            store.integrate(Node::Item(item), 0, Some(&mut ty))?;
29        }
30
31        Ok(())
32    }
33
34    fn _get(&self, key: &str) -> Option<Value> {
35        self.as_inner().ty().and_then(|ty| {
36            ty.map.get(key).and_then(|item| {
37                if let Some(item) = item.get() {
38                    if item.deleted() {
39                        return None;
40                    }
41
42                    Some(Value::from(&item.content))
43                } else {
44                    None
45                }
46            })
47        })
48    }
49
50    fn _contains_key(&self, key: &str) -> bool {
51        if let Some(ty) = self.as_inner().ty() {
52            ty.map
53                .get(key)
54                .and_then(|item| item.get())
55                .is_some_and(|item| !item.deleted())
56        } else {
57            false
58        }
59    }
60
61    fn _remove(&mut self, key: &str) {
62        if let Some((mut store, mut ty)) = self.as_inner().write()
63            && let Some(item) = ty.map.get(key).cloned()
64            && let Some(item) = item.get()
65        {
66            store.delete_item(item, Some(&mut ty));
67        }
68    }
69
70    fn _len(&self) -> u64 {
71        self._keys().count() as u64
72    }
73
74    fn _iter(&self) -> EntriesInnerIterator<'_> {
75        let ty = self.as_inner().ty();
76
77        if let Some(ty) = ty {
78            let ty = Rc::new(ty);
79
80            EntriesInnerIterator {
81                iter: Some(unsafe { &*Rc::as_ptr(&ty) }.map.iter()),
82                _lock: Some(ty),
83            }
84        } else {
85            EntriesInnerIterator {
86                _lock: None,
87                iter: None,
88            }
89        }
90    }
91
92    fn _keys(&self) -> KeysIterator<'_> {
93        KeysIterator(self._iter())
94    }
95
96    fn _values(&self) -> ValuesIterator<'_> {
97        ValuesIterator(self._iter())
98    }
99
100    fn _entries(&self) -> EntriesIterator<'_> {
101        EntriesIterator(self._iter())
102    }
103}
104
105pub(crate) struct EntriesInnerIterator<'a> {
106    _lock: Option<Rc<RwLockReadGuard<'a, YType>>>,
107    iter: Option<Iter<'a, SmolStr, ItemRef>>,
108}
109
110pub struct KeysIterator<'a>(EntriesInnerIterator<'a>);
111pub struct ValuesIterator<'a>(EntriesInnerIterator<'a>);
112pub struct EntriesIterator<'a>(EntriesInnerIterator<'a>);
113
114impl<'a> Iterator for EntriesInnerIterator<'a> {
115    type Item = (&'a str, &'a Item);
116
117    fn next(&mut self) -> Option<Self::Item> {
118        if let Some(iter) = &mut self.iter {
119            for (k, v) in iter {
120                if let Some(item) = v.get()
121                    && !item.deleted()
122                {
123                    return Some((k.as_str(), item));
124                }
125            }
126
127            None
128        } else {
129            None
130        }
131    }
132}
133
134impl<'a> Iterator for KeysIterator<'a> {
135    type Item = &'a str;
136
137    fn next(&mut self) -> Option<Self::Item> {
138        self.0.next().map(|(k, _)| k)
139    }
140}
141
142impl Iterator for ValuesIterator<'_> {
143    type Item = Value;
144
145    fn next(&mut self) -> Option<Self::Item> {
146        self.0.next().map(|(_, v)| Value::from(&v.content))
147    }
148}
149
150impl<'a> Iterator for EntriesIterator<'a> {
151    type Item = (&'a str, Value);
152
153    fn next(&mut self) -> Option<Self::Item> {
154        self.0.next().map(|(k, v)| (k, Value::from(&v.content)))
155    }
156}
157
158impl MapType for Map {}
159
160impl Map {
161    #[inline(always)]
162    pub fn id(&self) -> Option<Id> {
163        self._id()
164    }
165
166    #[inline(always)]
167    pub fn insert<V: Into<Value>>(&mut self, key: String, value: V) -> JwstCodecResult {
168        self._insert(key, value)
169    }
170
171    #[inline(always)]
172    pub fn get(&self, key: &str) -> Option<Value> {
173        self._get(key)
174    }
175
176    #[inline(always)]
177    pub fn contains_key(&self, key: &str) -> bool {
178        self._contains_key(key)
179    }
180
181    #[inline(always)]
182    pub fn remove(&mut self, key: &str) {
183        self._remove(key)
184    }
185
186    #[inline(always)]
187    pub fn len(&self) -> u64 {
188        self._len()
189    }
190
191    #[inline(always)]
192    pub fn is_empty(&self) -> bool {
193        self.len() == 0
194    }
195
196    #[inline(always)]
197    pub fn iter(&self) -> EntriesIterator<'_> {
198        self._entries()
199    }
200
201    #[inline(always)]
202    pub fn entries(&self) -> EntriesIterator<'_> {
203        self._entries()
204    }
205
206    #[inline(always)]
207    pub fn keys(&self) -> KeysIterator<'_> {
208        self._keys()
209    }
210
211    #[inline(always)]
212    pub fn values(&self) -> ValuesIterator<'_> {
213        self._values()
214    }
215}
216
217impl serde::Serialize for Map {
218    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
219        use serde::ser::SerializeMap;
220
221        let mut map = serializer.serialize_map(Some(self.len() as usize))?;
222        for (key, value) in self.iter() {
223            map.serialize_entry(&key, &value)?;
224        }
225        map.end()
226    }
227}
228
229#[cfg(test)]
230mod tests {
231    use super::*;
232    use crate::{Any, Doc, loom_model};
233
234    #[test]
235    fn test_map_basic() {
236        loom_model!({
237            let doc = Doc::new();
238            let mut map = doc.get_or_create_map("map").unwrap();
239            map.insert("1".to_string(), "value").unwrap();
240            assert_eq!(map.get("1").unwrap(), Value::Any(Any::String("value".to_string())));
241            assert!(!map.contains_key("nonexistent_key"));
242            assert_eq!(map.len(), 1);
243            assert!(map.contains_key("1"));
244            map.remove("1");
245            assert!(!map.contains_key("1"));
246            assert_eq!(map.len(), 0);
247        });
248    }
249
250    #[test]
251    fn test_map_equal() {
252        loom_model!({
253            let doc = Doc::new();
254            let mut map = doc.get_or_create_map("map").unwrap();
255            map.insert("1".to_string(), "value").unwrap();
256            map.insert("2".to_string(), false).unwrap();
257
258            let binary = doc.encode_update_v1().unwrap();
259            let new_doc = Doc::try_from_binary_v1(binary).unwrap();
260            let map = new_doc.get_or_create_map("map").unwrap();
261            assert_eq!(map.get("1").unwrap(), Value::Any(Any::String("value".to_string())));
262            assert_eq!(map.get("2").unwrap(), Value::Any(Any::False));
263            assert_eq!(map.len(), 2);
264        });
265    }
266
267    #[test]
268    fn test_map_renew_value() {
269        loom_model!({
270            let doc = Doc::new();
271            let mut map = doc.get_or_create_map("map").unwrap();
272            map.insert("1".to_string(), "value").unwrap();
273            map.insert("1".to_string(), "value2").unwrap();
274            assert_eq!(map.get("1").unwrap(), Value::Any(Any::String("value2".to_string())));
275            assert_eq!(map.len(), 1);
276        });
277    }
278
279    #[test]
280    fn test_map_re_encode() {
281        loom_model!({
282            let binary = {
283                let doc = Doc::new();
284                let mut map = doc.get_or_create_map("map").unwrap();
285                map.insert("1".to_string(), "value1").unwrap();
286                map.insert("2".to_string(), "value2").unwrap();
287                doc.encode_update_v1().unwrap()
288            };
289
290            {
291                let doc = Doc::try_from_binary_v1(binary).unwrap();
292                let map = doc.get_or_create_map("map").unwrap();
293                assert_eq!(map.get("1").unwrap(), Value::Any(Any::String("value1".to_string())));
294                assert_eq!(map.get("2").unwrap(), Value::Any(Any::String("value2".to_string())));
295            }
296        });
297    }
298
299    #[test]
300    fn test_map_iter() {
301        loom_model!({
302            let doc = Doc::new();
303            let mut map = doc.get_or_create_map("map").unwrap();
304            map.insert("1".to_string(), "value1").unwrap();
305            map.insert("2".to_string(), "value2").unwrap();
306            let mut vec = map.entries().collect::<Vec<_>>();
307
308            // hashmap iteration is in random order instead of insert order
309            vec.sort_by(|a, b| a.0.cmp(b.0));
310
311            assert_eq!(
312                vec,
313                vec![
314                    ("1", Value::Any(Any::String("value1".to_string()))),
315                    ("2", Value::Any(Any::String("value2".to_string())))
316                ]
317            )
318        });
319    }
320}