@@ -330,6 +330,74 @@ impl Element {
330
330
. map_err ( |e| Error :: CorruptedData ( e. to_string ( ) ) )
331
331
}
332
332
333
+ #[ cfg( feature = "full" ) ]
334
+ /// Insert a reference element in Merk under a key returning a delta.
335
+ pub fn insert_reference_if_changed_value < ' db , K : AsRef < [ u8 ] > , S : StorageContext < ' db > > (
336
+ & self ,
337
+ merk : & mut Merk < S > ,
338
+ key : K ,
339
+ referenced_value : Hash ,
340
+ options : Option < MerkOptions > ,
341
+ grove_version : & GroveVersion ,
342
+ ) -> CostResult < Delta , Error > {
343
+ check_grovedb_v0_with_cost ! (
344
+ "insert_reference" ,
345
+ grove_version. grovedb_versions. element. insert_reference
346
+ ) ;
347
+
348
+ let serialized = match self . serialize ( grove_version) {
349
+ Ok ( s) => s,
350
+ Err ( e) => return Err ( e) . wrap_with_cost ( Default :: default ( ) ) ,
351
+ } ;
352
+
353
+ let mut cost = OperationCost :: default ( ) ;
354
+
355
+ let previous_element = cost_return_on_error ! (
356
+ & mut cost,
357
+ Self :: get_optional( & merk, & key, true , grove_version)
358
+ ) ;
359
+ let delta = Delta {
360
+ new : self ,
361
+ old : previous_element,
362
+ } ;
363
+
364
+ if delta. has_changed ( ) {
365
+ let merk_feature_type = cost_return_on_error ! (
366
+ & mut cost,
367
+ self . get_feature_type( merk. is_sum_tree)
368
+ . wrap_with_cost( OperationCost :: default ( ) )
369
+ ) ;
370
+
371
+ let batch_operations = [ (
372
+ key,
373
+ Op :: PutCombinedReference ( serialized, referenced_value, merk_feature_type) ,
374
+ ) ] ;
375
+ let uses_sum_nodes = merk. is_sum_tree ;
376
+ cost_return_on_error ! (
377
+ & mut cost,
378
+ merk. apply_with_specialized_costs:: <_, Vec <u8 >>(
379
+ & batch_operations,
380
+ & [ ] ,
381
+ options,
382
+ & |key, value| {
383
+ Self :: specialized_costs_for_key_value(
384
+ key,
385
+ value,
386
+ uses_sum_nodes,
387
+ grove_version,
388
+ )
389
+ . map_err( |e| MerkError :: ClientCorruptionError ( e. to_string( ) ) )
390
+ } ,
391
+ Some ( & Element :: value_defined_cost_for_serialized_value) ,
392
+ grove_version,
393
+ )
394
+ . map_err( |e| Error :: CorruptedData ( e. to_string( ) ) )
395
+ ) ;
396
+ }
397
+
398
+ Ok ( delta) . wrap_with_cost ( cost)
399
+ }
400
+
333
401
#[ cfg( feature = "full" ) ]
334
402
/// Adds a "Put" op to batch operations with reference and key. Returns
335
403
/// CostResult.
@@ -363,11 +431,7 @@ impl Element {
363
431
}
364
432
365
433
#[ cfg( feature = "full" ) ]
366
- /// Insert a tree element in Merk under a key; path should be resolved
367
- /// and proper Merk should be loaded by this moment
368
- /// If transaction is not passed, the batch will be written immediately.
369
- /// If transaction is passed, the operation will be committed on the
370
- /// transaction commit.
434
+ /// Insert a tree element in Merk under a key.
371
435
pub fn insert_subtree < ' db , K : AsRef < [ u8 ] > , S : StorageContext < ' db > > (
372
436
& self ,
373
437
merk : & mut Merk < S > ,
@@ -417,6 +481,85 @@ impl Element {
417
481
. map_err ( |e| Error :: CorruptedData ( e. to_string ( ) ) )
418
482
}
419
483
484
+ #[ cfg( feature = "full" ) ]
485
+ /// Insert a tree element in Merk under a key, returning delta.
486
+ pub fn insert_subtree_if_changed < ' db , K : AsRef < [ u8 ] > , S : StorageContext < ' db > > (
487
+ & self ,
488
+ merk : & mut Merk < S > ,
489
+ key : K ,
490
+ subtree_root_hash : Hash ,
491
+ options : Option < MerkOptions > ,
492
+ grove_version : & GroveVersion ,
493
+ ) -> CostResult < Delta , Error > {
494
+ check_grovedb_v0_with_cost ! (
495
+ "insert_subtree" ,
496
+ grove_version. grovedb_versions. element. insert_subtree
497
+ ) ;
498
+
499
+ let serialized = match self . serialize ( grove_version) {
500
+ Ok ( s) => s,
501
+ Err ( e) => return Err ( e) . wrap_with_cost ( Default :: default ( ) ) ,
502
+ } ;
503
+
504
+ let mut cost = OperationCost :: default ( ) ;
505
+
506
+ let previous_element = cost_return_on_error ! (
507
+ & mut cost,
508
+ Self :: get_optional( & merk, & key, true , grove_version)
509
+ ) ;
510
+
511
+ let delta = Delta {
512
+ new : self ,
513
+ old : previous_element,
514
+ } ;
515
+
516
+ if delta. has_changed ( ) {
517
+ let merk_feature_type =
518
+ cost_return_on_error_no_add ! ( cost, self . get_feature_type( merk. is_sum_tree) ) ;
519
+
520
+ let tree_cost =
521
+ cost_return_on_error_no_add ! ( cost, self . get_specialized_cost( grove_version) ) ;
522
+
523
+ let specialized_cost = tree_cost
524
+ + self . get_flags ( ) . as_ref ( ) . map_or ( 0 , |flags| {
525
+ let flags_len = flags. len ( ) as u32 ;
526
+ flags_len + flags_len. required_space ( ) as u32
527
+ } ) ;
528
+ let batch_operations = [ (
529
+ key,
530
+ Op :: PutLayeredReference (
531
+ serialized,
532
+ specialized_cost,
533
+ subtree_root_hash,
534
+ merk_feature_type,
535
+ ) ,
536
+ ) ] ;
537
+ let uses_sum_nodes = merk. is_sum_tree ;
538
+ cost_return_on_error ! (
539
+ & mut cost,
540
+ merk. apply_with_specialized_costs:: <_, Vec <u8 >>(
541
+ & batch_operations,
542
+ & [ ] ,
543
+ options,
544
+ & |key, value| {
545
+ Self :: specialized_costs_for_key_value(
546
+ key,
547
+ value,
548
+ uses_sum_nodes,
549
+ grove_version,
550
+ )
551
+ . map_err( |e| MerkError :: ClientCorruptionError ( e. to_string( ) ) )
552
+ } ,
553
+ Some ( & Element :: value_defined_cost_for_serialized_value) ,
554
+ grove_version,
555
+ )
556
+ . map_err( |e| Error :: CorruptedData ( e. to_string( ) ) )
557
+ ) ;
558
+ }
559
+
560
+ Ok ( delta) . wrap_with_cost ( cost)
561
+ }
562
+
420
563
#[ cfg( feature = "full" ) ]
421
564
/// Adds a "Put" op to batch operations for a subtree and key
422
565
pub fn insert_subtree_into_batch_operations < K : AsRef < [ u8 ] > > (
0 commit comments