y_octo/doc/types/
array.rs

1use super::*;
2
3impl_type!(Array);
4
5impl ListType for Array {}
6
7pub struct ArrayIter(ListIterator);
8
9impl Iterator for ArrayIter {
10    type Item = Value;
11
12    fn next(&mut self) -> Option<Self::Item> {
13        for item in self.0.by_ref() {
14            if let Some(item) = item.get() {
15                if item.countable() {
16                    return Some(item.content.as_ref().try_into().unwrap());
17                }
18            }
19        }
20
21        None
22    }
23}
24
25impl Array {
26    #[inline]
27    pub fn len(&self) -> u64 {
28        self.content_len()
29    }
30
31    #[inline]
32    pub fn is_empty(&self) -> bool {
33        self.len() == 0
34    }
35
36    pub fn get(&self, index: u64) -> Option<Value> {
37        let (item, offset) = self.get_item_at(index)?;
38        // array only store 1-unit elements
39        debug_assert!(offset == 0);
40        if let Some(item) = item.get() {
41            // TODO: rewrite to content.read(&mut [Any])
42            return match item.content.as_ref() {
43                Content::Any(any) => return any.first().map(|any| Value::Any(any.clone())),
44                _ => item.content.as_ref().try_into().map_or_else(|_| None, Some),
45            };
46        }
47
48        None
49    }
50
51    pub fn iter(&self) -> ArrayIter {
52        ArrayIter(self.iter_item())
53    }
54
55    pub fn push<V: Into<Value>>(&mut self, val: V) -> JwstCodecResult {
56        self.insert(self.len(), val)
57    }
58
59    pub fn insert<V: Into<Value>>(&mut self, idx: u64, val: V) -> JwstCodecResult {
60        self.insert_at(idx, val.into().into())
61    }
62
63    pub fn remove(&mut self, idx: u64, len: u64) -> JwstCodecResult {
64        self.remove_at(idx, len)
65    }
66}
67
68impl serde::Serialize for Array {
69    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70    where
71        S: serde::Serializer,
72    {
73        use serde::ser::SerializeSeq;
74
75        let mut seq = serializer.serialize_seq(Some(self.len() as usize))?;
76
77        for item in self.iter() {
78            seq.serialize_element(&item)?;
79        }
80        seq.end()
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use yrs::{Array, Options, Text, Transact};
87
88    use super::*;
89
90    #[test]
91    fn test_yarray_insert() {
92        let options = DocOptions {
93            client: Some(rand::random()),
94            guid: Some(nanoid::nanoid!()),
95        };
96
97        loom_model!({
98            let doc = Doc::with_options(options.clone());
99            let mut array = doc.get_or_create_array("abc").unwrap();
100
101            array.insert(0, " ").unwrap();
102            array.insert(0, "Hello").unwrap();
103            array.insert(2, "World").unwrap();
104
105            assert_eq!(array.get(0).unwrap(), Value::Any(Any::String("Hello".into())));
106            assert_eq!(array.get(1).unwrap(), Value::Any(Any::String(" ".into())));
107            assert_eq!(array.get(2).unwrap(), Value::Any(Any::String("World".into())));
108        });
109    }
110
111    #[test]
112    #[cfg_attr(miri, ignore)]
113    fn test_ytext_equal() {
114        let options = DocOptions {
115            client: Some(rand::random()),
116            guid: Some(nanoid::nanoid!()),
117        };
118        let yrs_options = Options {
119            client_id: rand::random(),
120            guid: nanoid::nanoid!().into(),
121            ..Default::default()
122        };
123
124        loom_model!({
125            let doc = yrs::Doc::with_options(yrs_options.clone());
126            let array = doc.get_or_insert_text("abc");
127
128            let mut trx = doc.transact_mut();
129            array.insert(&mut trx, 0, " ").unwrap();
130            array.insert(&mut trx, 0, "Hello").unwrap();
131            array.insert(&mut trx, 6, "World").unwrap();
132            array.insert(&mut trx, 11, "!").unwrap();
133            let buffer = trx.encode_update_v1().unwrap();
134
135            let mut decoder = RawDecoder::new(buffer);
136            let update = Update::read(&mut decoder).unwrap();
137
138            let mut doc = Doc::with_options(options.clone());
139            doc.apply_update(update).unwrap();
140            let array = doc.get_or_create_array("abc").unwrap();
141
142            assert_eq!(array.get(0).unwrap(), Value::Any(Any::String("Hello".into())));
143            assert_eq!(array.get(5).unwrap(), Value::Any(Any::String(" ".into())));
144            assert_eq!(array.get(6).unwrap(), Value::Any(Any::String("World".into())));
145            assert_eq!(array.get(11).unwrap(), Value::Any(Any::String("!".into())));
146        });
147
148        let options = DocOptions {
149            client: Some(rand::random()),
150            guid: Some(nanoid::nanoid!()),
151        };
152        let yrs_options = Options {
153            client_id: rand::random(),
154            guid: nanoid::nanoid!().into(),
155            ..Default::default()
156        };
157        loom_model!({
158            let doc = yrs::Doc::with_options(yrs_options.clone());
159            let array = doc.get_or_insert_text("abc");
160
161            let mut trx = doc.transact_mut();
162            array.insert(&mut trx, 0, "Hello").unwrap();
163            array.insert(&mut trx, 5, " ").unwrap();
164            array.insert(&mut trx, 6, "World").unwrap();
165            array.insert(&mut trx, 11, "!").unwrap();
166            let buffer = trx.encode_update_v1().unwrap();
167
168            let mut decoder = RawDecoder::new(buffer);
169            let update = Update::read(&mut decoder).unwrap();
170
171            let mut doc = Doc::with_options(options.clone());
172            doc.apply_update(update).unwrap();
173            let array = doc.get_or_create_array("abc").unwrap();
174
175            assert_eq!(array.get(0).unwrap(), Value::Any(Any::String("Hello".into())));
176            assert_eq!(array.get(5).unwrap(), Value::Any(Any::String(" ".into())));
177            assert_eq!(array.get(6).unwrap(), Value::Any(Any::String("World".into())));
178            assert_eq!(array.get(11).unwrap(), Value::Any(Any::String("!".into())));
179        });
180    }
181
182    #[test]
183    #[cfg_attr(miri, ignore)]
184    fn test_yrs_array_decode() {
185        let update = {
186            let doc = yrs::Doc::new();
187            let array = doc.get_or_insert_array("abc");
188            let mut trx = doc.transact_mut();
189
190            array.insert(&mut trx, 0, "hello").unwrap();
191            array.insert(&mut trx, 1, "world").unwrap();
192            array.insert(&mut trx, 1, " ").unwrap();
193
194            trx.encode_update_v1().unwrap()
195        };
196
197        loom_model!({
198            let doc = Doc::new_from_binary_with_options(
199                update.clone(),
200                DocOptions {
201                    guid: Some(String::from("1")),
202                    client: Some(1),
203                },
204            )
205            .unwrap();
206            let arr = doc.get_or_create_array("abc").unwrap();
207
208            assert_eq!(arr.get(2).unwrap(), Value::Any(Any::String("world".to_string())))
209        });
210    }
211}