1
1
use std:: {
2
+ cell:: RefCell ,
2
3
collections:: { HashMap , HashSet } ,
3
4
ops:: { Deref , DerefMut } ,
4
5
sync:: Arc ,
@@ -130,7 +131,8 @@ impl Doc {
130
131
offset : u64 ,
131
132
) -> JwstCodecResult < ( ) > {
132
133
self . repair ( & mut struct_info) ?;
133
- match & mut struct_info {
134
+ let struct_info = Arc :: new ( RefCell :: new ( struct_info) ) ;
135
+ match struct_info. borrow_mut ( ) . deref_mut ( ) {
134
136
StructInfo :: Item { id, item } => {
135
137
let mut left =
136
138
item. left_id
@@ -139,17 +141,35 @@ impl Doc {
139
141
_ => None ,
140
142
} ) ;
141
143
142
- let right =
144
+ let mut right =
143
145
item. right_id
144
146
. and_then ( |right_id| match self . store . get_item ( right_id) {
145
147
Ok ( right) => Some ( right) ,
146
148
_ => None ,
147
149
} ) ;
148
150
149
- let parent = item. parent . as_ref ( ) . and_then ( |parent| match parent {
150
- Parent :: String ( _) => todo ! ( ) ,
151
- Parent :: Id ( id) => Some ( * id) ,
152
- } ) ;
151
+ let parent = if let Some ( parent) = & item. parent {
152
+ match parent {
153
+ Parent :: String ( name) => Some ( self . store . get_or_create_type ( name) ) ,
154
+ Parent :: Id ( id) => {
155
+ if let Some ( item) = self . store . get_item ( * id) ?. borrow ( ) . item ( ) {
156
+ match & item. content {
157
+ Content :: Type ( ytype) => {
158
+ Some ( Arc :: new ( RefCell :: new ( ytype. clone ( ) . into ( ) ) ) )
159
+ }
160
+ Content :: Deleted ( _) => None ,
161
+ _ => {
162
+ return Err ( JwstCodecError :: InvalidParent ) ;
163
+ }
164
+ }
165
+ } else {
166
+ None
167
+ }
168
+ }
169
+ }
170
+ } else {
171
+ None
172
+ } ;
153
173
154
174
if offset > 0 {
155
175
id. clock += offset;
@@ -160,7 +180,8 @@ impl Doc {
160
180
item. content . split ( offset) ?;
161
181
}
162
182
163
- if let Some ( _parent_id) = parent {
183
+ if let Some ( parent) = parent {
184
+ let mut parent = parent. borrow_mut ( ) ;
164
185
let right_is_null_or_has_left = match & right {
165
186
None => true ,
166
187
Some ( right) => right. left_id ( ) . is_some ( ) ,
@@ -176,35 +197,37 @@ impl Doc {
176
197
{
177
198
// set the first conflicting item
178
199
let mut o = if let Some ( left) = left. clone ( ) {
179
- left. right_id ( )
180
- } else if let Some ( _sub) = & item. parent_sub {
181
- // TODO: handle parent_sub, set if parent is Map or Array
182
- unimplemented ! ( )
200
+ Some ( left)
201
+ } else if let Some ( parent_sub) = & item. parent_sub {
202
+ let o = parent. map . get ( parent_sub) . cloned ( ) ;
203
+ if let Some ( o) = o. as_ref ( ) {
204
+ Some ( self . store . get_start_item ( o. clone ( ) ) )
205
+ } else {
206
+ None
207
+ }
183
208
} else {
184
- // TODO: handle parent w/o sub, occurs if parent is Text
185
- unimplemented ! ( )
209
+ parent. start . clone ( )
186
210
} ;
187
211
188
212
let mut conflicting_items = HashSet :: new ( ) ;
189
213
let mut items_before_origin = HashSet :: new ( ) ;
190
214
191
- while let Some ( conflict_id) = o {
192
- match right {
193
- Some ( right) if right. id ( ) == & conflict_id => {
194
- break ;
195
- }
196
- _ => { }
197
- } ;
198
-
199
- items_before_origin. insert ( conflict_id) ;
200
- conflicting_items. insert ( conflict_id) ;
201
- let conflict_item = self . store . get_item ( conflict_id) ?;
202
- match conflict_item. as_ref ( ) {
203
- StructInfo :: Item { item : c, .. } => {
215
+ while let Some ( conflict) = o {
216
+ if Some ( conflict. clone ( ) ) == right {
217
+ break ;
218
+ }
219
+
220
+ items_before_origin. insert ( conflict. id ( ) ) ;
221
+ conflicting_items. insert ( conflict. id ( ) ) ;
222
+ match conflict. borrow ( ) . deref ( ) {
223
+ StructInfo :: Item {
224
+ id : conflict_id,
225
+ item : c,
226
+ } => {
204
227
if item. left_id == c. left_id {
205
228
// case 1
206
229
if conflict_id. client < id. client {
207
- left = Some ( Arc :: clone ( & conflict_item ) ) ;
230
+ left = Some ( conflict . clone ( ) ) ;
208
231
conflicting_items. clear ( ) ;
209
232
} else if item. right_id == c. right_id {
210
233
// `this` and `c` are conflicting and point to the same
@@ -216,20 +239,66 @@ impl Doc {
216
239
if items_before_origin. contains ( & conflict_item_left)
217
240
&& !conflicting_items. contains ( & conflict_item_left)
218
241
{
219
- left = Some ( Arc :: clone ( & conflict_item ) ) ;
242
+ left = Some ( conflict . clone ( ) ) ;
220
243
conflicting_items. clear ( ) ;
221
244
}
222
245
} else {
223
246
break ;
224
247
}
225
- o = conflict_item. right_id ( ) ;
248
+ o = match c. right_id {
249
+ Some ( right_id) => Some ( self . store . get_item ( right_id) ?) ,
250
+ None => None ,
251
+ } ;
226
252
}
227
253
_ => {
228
254
break ;
229
255
}
230
256
}
231
257
}
232
- item. left_id = left. map ( |item| * item. id ( ) )
258
+
259
+ // reconnect left/right
260
+ match left {
261
+ // has left, connect left <-> self <-> left.right
262
+ Some ( left) => {
263
+ item. left_id = Some ( left. id ( ) ) ;
264
+ left. modify ( |left| {
265
+ if let StructInfo :: Item { item : left, .. } = left {
266
+ left. right_id = left. right_id . replace ( * id) ;
267
+ }
268
+ } ) ;
269
+ }
270
+ // no left, right = parent.start
271
+ None => {
272
+ right = if let Some ( parent_sub) = & item. parent_sub {
273
+ if let Some ( r) = parent. map . get ( parent_sub) . cloned ( ) {
274
+ Some ( self . store . get_start_item ( r) )
275
+ } else {
276
+ None
277
+ }
278
+ } else {
279
+ parent. start . clone ( )
280
+ } ;
281
+ }
282
+ }
283
+
284
+ match right {
285
+ // has right, connect
286
+ Some ( right) => right. modify ( |right| {
287
+ if let StructInfo :: Item { item : right, .. } = right {
288
+ right. left_id = right. left_id . replace ( * id) ;
289
+ }
290
+ item. right_id = Some ( right. id ( ) ) ;
291
+ } ) ,
292
+ // no right, parent.start = item, delete item.left
293
+ None => {
294
+ if let Some ( parent_sub) = & item. parent_sub {
295
+ parent
296
+ . map
297
+ . insert ( parent_sub. to_string ( ) , struct_info. clone ( ) . into ( ) ) ;
298
+ }
299
+ // left.delete();
300
+ }
301
+ }
233
302
}
234
303
}
235
304
}
@@ -243,19 +312,34 @@ impl Doc {
243
312
// skip ignored
244
313
}
245
314
}
246
- self . store . add_item ( struct_info)
315
+ self . store . add_item_ref ( struct_info. into ( ) )
247
316
}
248
317
249
318
fn repair ( & mut self , info : & mut StructInfo ) -> JwstCodecResult {
250
319
if let StructInfo :: Item { item, .. } = info {
251
320
if let Some ( left_id) = item. left_id {
252
321
let left = self . store . get_item_clean_end ( left_id) ?;
253
- item. left_id = Some ( * left. id ( ) ) ;
322
+ item. left_id = Some ( left. id ( ) ) ;
254
323
}
255
324
256
325
if let Some ( right_id) = item. right_id {
257
326
let right = self . store . get_item_clean_start ( right_id) ?;
258
- item. right_id = Some ( * right. id ( ) ) ;
327
+ item. right_id = Some ( right. id ( ) ) ;
328
+ }
329
+
330
+ if let Some ( parent) = item. parent . take ( ) {
331
+ match parent {
332
+ Parent :: String ( str) => {
333
+ self . store . get_or_create_type ( & str) ;
334
+ }
335
+ Parent :: Id ( parent_id) => {
336
+ let parent = self . store . get_item ( parent_id) ?;
337
+ if !parent. is_item ( ) {
338
+ item. parent = None
339
+ }
340
+ }
341
+ }
342
+ } else {
259
343
}
260
344
}
261
345
0 commit comments