y_octo/doc/types/
array.rs

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