@@ -27,33 +27,30 @@ pub struct Serializer {
27
27
thc : ObjectCache < Bytes32 > ,
28
28
slc : ObjectCache < u64 > ,
29
29
30
+ sentinel : Option < NodePtr > ,
30
31
output : Cursor < Vec < u8 > > ,
31
32
}
32
33
33
- impl Default for Serializer {
34
- fn default ( ) -> Self {
35
- Self :: new ( )
36
- }
37
- }
38
-
39
34
#[ derive( Clone ) ]
40
35
pub struct UndoState {
41
36
read_op_stack : Vec < ReadOp > ,
42
37
write_stack : Vec < NodePtr > ,
38
+ read_cache_lookup : ReadCacheLookup ,
43
39
output_position : u64 ,
44
40
}
45
41
46
42
/// The state to allow incrementally serializing CLVM structures with back-refs
47
43
/// The compression cannot "see through" the sentinel node, so some compression
48
44
/// opportunities may be missed when serializing and compressing incrementally.
49
45
impl Serializer {
50
- pub fn new ( ) -> Self {
46
+ pub fn new ( sentinel : Option < NodePtr > ) -> Self {
51
47
Self {
52
48
read_op_stack : vec ! [ ReadOp :: Parse ] ,
53
49
write_stack : vec ! [ ] ,
54
50
read_cache_lookup : ReadCacheLookup :: new ( ) ,
55
51
thc : ObjectCache :: new ( treehash) ,
56
52
slc : ObjectCache :: new ( serialized_length) ,
53
+ sentinel,
57
54
output : Cursor :: new ( vec ! [ ] ) ,
58
55
}
59
56
}
@@ -72,25 +69,21 @@ impl Serializer {
72
69
/// beginning if this is the first call. Returns true when we're done
73
70
/// serializing. i.e. no sentinel token was encountered. Once this function
74
71
/// returns true, it may not be called again.
75
- pub fn add (
76
- & mut self ,
77
- a : & Allocator ,
78
- node : NodePtr ,
79
- sentinel : Option < NodePtr > ,
80
- ) -> io:: Result < ( bool , UndoState ) > {
72
+ pub fn add ( & mut self , a : & Allocator , node : NodePtr ) -> io:: Result < ( bool , UndoState ) > {
81
73
// once we're done serializing (i.e. there was no sentinel in the last
82
74
// call to add()), we can't resume
83
75
assert ! ( !self . read_op_stack. is_empty( ) ) ;
84
76
85
77
let undo_state = UndoState {
86
78
read_op_stack : self . read_op_stack . clone ( ) ,
87
79
write_stack : self . write_stack . clone ( ) ,
80
+ read_cache_lookup : self . read_cache_lookup . clone ( ) ,
88
81
output_position : self . output . position ( ) ,
89
82
} ;
90
83
self . write_stack . push ( node) ;
91
84
92
85
while let Some ( node_to_write) = self . write_stack . pop ( ) {
93
- if Some ( node_to_write) == sentinel {
86
+ if Some ( node_to_write) == self . sentinel {
94
87
// we're not done serializing yet, we're stopping, and the
95
88
// caller will call add() again with the node to serialize
96
89
// here
@@ -99,8 +92,9 @@ impl Serializer {
99
92
let op = self . read_op_stack . pop ( ) ;
100
93
assert ! ( op == Some ( ReadOp :: Parse ) ) ;
101
94
102
- let node_serialized_length = self . slc . get_or_calculate ( a, & node_to_write, sentinel) ;
103
- let node_tree_hash = self . thc . get_or_calculate ( a, & node_to_write, sentinel) ;
95
+ let node_serialized_length =
96
+ self . slc . get_or_calculate ( a, & node_to_write, self . sentinel ) ;
97
+ let node_tree_hash = self . thc . get_or_calculate ( a, & node_to_write, self . sentinel ) ;
104
98
if let ( Some ( node_tree_hash) , Some ( node_serialized_length) ) =
105
99
( node_tree_hash, node_serialized_length)
106
100
{
@@ -148,6 +142,7 @@ impl Serializer {
148
142
pub fn restore ( & mut self , state : UndoState ) {
149
143
self . read_op_stack = state. read_op_stack ;
150
144
self . write_stack = state. write_stack ;
145
+ self . read_cache_lookup = state. read_cache_lookup ;
151
146
self . output . set_position ( state. output_position ) ;
152
147
self . output
153
148
. get_mut ( )
@@ -168,8 +163,6 @@ impl Serializer {
168
163
/// It's only valid to convert to the inner serialized form once
169
164
/// serialization is complete. i.e. after add() returns true.
170
165
pub fn into_inner ( self ) -> Vec < u8 > {
171
- // if the sentinel is set, it means we're in the middle of serialization
172
- // still
173
166
assert ! ( self . read_op_stack. is_empty( ) ) ;
174
167
self . output . into_inner ( )
175
168
}
@@ -192,18 +185,18 @@ mod tests {
192
185
let item = node_from_bytes ( & mut a, & hex ! ( "ffff0102ff0304" ) ) . unwrap ( ) ;
193
186
let list = a. new_pair ( item, sentinel) . unwrap ( ) ;
194
187
195
- let mut ser = Serializer :: new ( ) ;
188
+ let mut ser = Serializer :: new ( Some ( sentinel ) ) ;
196
189
let mut size = ser. size ( ) ;
197
190
for _ in 0 ..10 {
198
191
// this keeps returning false because we encounter a sentinel
199
- let ( done, _) = ser. add ( & a, list, Some ( sentinel ) ) . unwrap ( ) ;
192
+ let ( done, _) = ser. add ( & a, list) . unwrap ( ) ;
200
193
assert ! ( !done) ;
201
194
assert ! ( ser. size( ) > size) ;
202
195
size = ser. size ( ) ;
203
196
}
204
197
205
198
// this returns true because we're done now
206
- let ( done, _) = ser. add ( & a, NodePtr :: NIL , None ) . unwrap ( ) ;
199
+ let ( done, _) = ser. add ( & a, NodePtr :: NIL ) . unwrap ( ) ;
207
200
assert ! ( done) ;
208
201
209
202
let output = ser. into_inner ( ) ;
@@ -243,10 +236,10 @@ mod tests {
243
236
let node5 = a. new_pair ( node3, node4) . unwrap ( ) ;
244
237
let item = a. new_pair ( node2, node5) . unwrap ( ) ;
245
238
246
- let mut ser = Serializer :: new ( ) ;
239
+ let mut ser = Serializer :: new ( Some ( sentinel ) ) ;
247
240
let mut size = ser. size ( ) ;
248
241
249
- let ( done, _) = ser. add ( & a, item, Some ( sentinel ) ) . unwrap ( ) ;
242
+ let ( done, _) = ser. add ( & a, item) . unwrap ( ) ;
250
243
assert ! ( !done) ;
251
244
assert ! ( ser. size( ) > size) ;
252
245
size = ser. size ( ) ;
@@ -261,14 +254,14 @@ mod tests {
261
254
262
255
for _ in 0 ..10 {
263
256
// this keeps returning false because we encounter a sentinel
264
- let ( done, _) = ser. add ( & a, item, Some ( sentinel ) ) . unwrap ( ) ;
257
+ let ( done, _) = ser. add ( & a, item) . unwrap ( ) ;
265
258
assert ! ( !done) ;
266
259
assert ! ( ser. size( ) > size) ;
267
260
size = ser. size ( ) ;
268
261
}
269
262
270
263
// this returns true because we're done now
271
- let ( done, _) = ser. add ( & a, NodePtr :: NIL , None ) . unwrap ( ) ;
264
+ let ( done, _) = ser. add ( & a, NodePtr :: NIL ) . unwrap ( ) ;
272
265
assert ! ( done) ;
273
266
274
267
// The "foobar" atom is serialized as 86666f6f626172
@@ -299,13 +292,13 @@ mod tests {
299
292
let item = node_from_bytes ( & mut a, & hex ! ( "ffff0102ff0304" ) ) . unwrap ( ) ;
300
293
let list = a. new_pair ( item, sentinel) . unwrap ( ) ;
301
294
302
- let mut ser = Serializer :: new ( ) ;
303
- let ( done, _) = ser. add ( & a, list, Some ( sentinel ) ) . unwrap ( ) ;
295
+ let mut ser = Serializer :: new ( Some ( sentinel ) ) ;
296
+ let ( done, _) = ser. add ( & a, list) . unwrap ( ) ;
304
297
assert ! ( !done) ;
305
298
assert_eq ! ( ser. size( ) , 8 ) ;
306
299
assert_eq ! ( hex:: encode( ser. get_ref( ) ) , "ffffff0102ff0304" ) ;
307
300
308
- let ( done, state) = ser. add ( & a, NodePtr :: NIL , None ) . unwrap ( ) ;
301
+ let ( done, state) = ser. add ( & a, NodePtr :: NIL ) . unwrap ( ) ;
309
302
assert ! ( done) ;
310
303
assert_eq ! ( ser. size( ) , 9 ) ;
311
304
assert_eq ! ( hex:: encode( ser. get_ref( ) ) , "ffffff0102ff030480" ) ;
@@ -315,17 +308,17 @@ mod tests {
315
308
assert_eq ! ( ser. size( ) , 8 ) ;
316
309
assert_eq ! ( hex:: encode( ser. get_ref( ) ) , "ffffff0102ff0304" ) ;
317
310
318
- let ( done, _) = ser. add ( & a, item, None ) . unwrap ( ) ;
311
+ let ( done, _) = ser. add ( & a, item) . unwrap ( ) ;
319
312
assert ! ( done) ;
320
313
321
314
assert_eq ! ( ser. size( ) , 10 ) ;
322
- assert_eq ! ( hex:: encode( ser. get_ref( ) ) , "ffffff0102ff0304fe04 " ) ;
315
+ assert_eq ! ( hex:: encode( ser. get_ref( ) ) , "ffffff0102ff0304fe02 " ) ;
323
316
324
317
ser. restore ( state) ;
325
318
326
319
let item = a. new_small_number ( 1337 ) . unwrap ( ) ;
327
320
328
- let ( done, _) = ser. add ( & a, item, None ) . unwrap ( ) ;
321
+ let ( done, _) = ser. add ( & a, item) . unwrap ( ) ;
329
322
330
323
assert ! ( done) ;
331
324
assert_eq ! ( ser. size( ) , 11 ) ;
@@ -334,4 +327,132 @@ mod tests {
334
327
let output = ser. into_inner ( ) ;
335
328
assert_eq ! ( hex:: encode( & output) , "ffffff0102ff0304820539" ) ;
336
329
}
330
+
331
+ #[ test]
332
+ fn test_incremental_restore ( ) {
333
+ let mut a = Allocator :: new ( ) ;
334
+
335
+ let sentinel = a. new_pair ( NodePtr :: NIL , NodePtr :: NIL ) . unwrap ( ) ;
336
+ // ((0x000000000000 . 0x111111111111) . (0x222222222222 . 0x333333333333))
337
+ let item = node_from_bytes (
338
+ & mut a,
339
+ & hex ! ( "ffff8600000000000086111111111111ff8622222222222286333333333333" ) ,
340
+ )
341
+ . unwrap ( ) ;
342
+ let item1 = a. new_pair ( item, sentinel) . unwrap ( ) ;
343
+
344
+ // ((0x111111111111 . 0x000000000000) . (0x222222222222 . 0x333333333333))
345
+ let item = node_from_bytes (
346
+ & mut a,
347
+ & hex ! ( "ffff8611111111111186000000000000ff8622222222222286333333333333" ) ,
348
+ )
349
+ . unwrap ( ) ;
350
+ let item2 = a. new_pair ( item, sentinel) . unwrap ( ) ;
351
+
352
+ // ((0x000000000000 . 0x111111111111) . (0x333333333333 . 0x222222222222))
353
+ let item = node_from_bytes (
354
+ & mut a,
355
+ & hex ! ( "ffff8600000000000086111111111111ff8633333333333386222222222222" ) ,
356
+ )
357
+ . unwrap ( ) ;
358
+ let item3 = a. new_pair ( item, sentinel) . unwrap ( ) ;
359
+
360
+ // add item1, item2, item3
361
+ // restore to after item1
362
+ // add item3, item2
363
+ // terminate the list
364
+ let mut ser = Serializer :: new ( Some ( sentinel) ) ;
365
+ let ( done, _) = ser. add ( & a, item1) . unwrap ( ) ;
366
+ assert ! ( !done) ;
367
+ println ! ( "{}" , hex:: encode( ser. get_ref( ) ) ) ;
368
+ let ( done, restore_state) = ser. add ( & a, item2) . unwrap ( ) ;
369
+ assert ! ( !done) ;
370
+ println ! ( "{}" , hex:: encode( ser. get_ref( ) ) ) ;
371
+ let ( done, _) = ser. add ( & a, item3) . unwrap ( ) ;
372
+ assert ! ( !done) ;
373
+ println ! ( "{}" , hex:: encode( ser. get_ref( ) ) ) ;
374
+ println ! ( "restore" ) ;
375
+ ser. restore ( restore_state) ;
376
+ println ! ( "{}" , hex:: encode( ser. get_ref( ) ) ) ;
377
+
378
+ let ( done, _) = ser. add ( & a, item3) . unwrap ( ) ;
379
+ assert ! ( !done) ;
380
+ println ! ( "{}" , hex:: encode( ser. get_ref( ) ) ) ;
381
+ let ( done, _) = ser. add ( & a, item2) . unwrap ( ) ;
382
+ assert ! ( !done) ;
383
+ println ! ( "{}" , hex:: encode( ser. get_ref( ) ) ) ;
384
+
385
+ let ( done, _) = ser. add ( & a, NodePtr :: NIL ) . unwrap ( ) ;
386
+ assert ! ( done) ;
387
+ println ! ( "{}" , hex:: encode( ser. get_ref( ) ) ) ;
388
+
389
+ let output = ser. into_inner ( ) ;
390
+
391
+ {
392
+ let mut a = Allocator :: new ( ) ;
393
+ let result = node_from_bytes_backrefs ( & mut a, & output) . expect ( "invalid serialization" ) ;
394
+ let roundtrip = node_to_bytes ( & a, result) . expect ( "failed to serialize" ) ;
395
+ assert_eq ! (
396
+ hex:: encode( roundtrip) ,
397
+ "
398
+ ff
399
+ ff
400
+ ff
401
+ 86000000000000
402
+ 86111111111111
403
+ ff
404
+ 86222222222222
405
+ 86333333333333
406
+ ff
407
+ ff
408
+ ff
409
+ 86000000000000
410
+ 86111111111111
411
+ ff
412
+ 86333333333333
413
+ 86222222222222
414
+ ff
415
+ ff
416
+ ff
417
+ 86111111111111
418
+ 86000000000000
419
+ ff
420
+ 86222222222222
421
+ 86333333333333
422
+ 80"
423
+ . chars( )
424
+ . filter( |c| !c. is_whitespace( ) )
425
+ . collect:: <String >( )
426
+ ) ;
427
+ }
428
+
429
+ assert_eq ! (
430
+ hex:: encode( output) ,
431
+ "
432
+ ff
433
+ ff
434
+ ff
435
+ 86000000000000
436
+ 86111111111111
437
+ ff
438
+ 86222222222222
439
+ 86333333333333
440
+ ff
441
+ ff
442
+ fe04
443
+ ff
444
+ fe1d
445
+ fe2b
446
+ ff
447
+ ff
448
+ ff
449
+ fe0c
450
+ fe11
451
+ fe1b
452
+ 80"
453
+ . chars( )
454
+ . filter( |c| !c. is_whitespace( ) )
455
+ . collect:: <String >( )
456
+ ) ;
457
+ }
337
458
}
0 commit comments