y_octo/doc/types/
array.rs1use 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 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}