@@ -106,8 +106,6 @@ type Node[T HamtValue[T]] struct {
106
106
107
107
// for fetching and storing children
108
108
store cbor.IpldStore
109
-
110
- zeroValue T
111
109
}
112
110
113
111
// Pointer is an element in a HAMT node's Pointers array, encoded as an IPLD
@@ -200,7 +198,7 @@ func NewNode[T HamtValue[T]](cs cbor.IpldStore, options ...Option) (*Node[T], er
200
198
}
201
199
}
202
200
203
- return newNode [T ](cs , cfg .hashFn , cfg .bitWidth , zero [ T ]() ), nil
201
+ return newNode [T ](cs , cfg .hashFn , cfg .bitWidth ), nil
204
202
}
205
203
206
204
// Find navigates through the HAMT structure to where key `k` should exist. If
@@ -234,19 +232,18 @@ func (n *Node[T]) Find(ctx context.Context, k string) (T, bool, error) {
234
232
// further nodes.
235
233
func (n * Node [T ]) Delete (ctx context.Context , k string ) (bool , error ) {
236
234
kb := []byte (k )
237
- modified , err := n .modifyValue (ctx , & hashBits {b : n .hash (kb )}, kb , n . zeroValue , OVERWRITE )
235
+ modified , err := n .modifyValue (ctx , & hashBits {b : n .hash (kb )}, kb , zero [ T ](), true , OVERWRITE )
238
236
return modified == MODIFIED , err
239
237
}
240
238
241
239
// Constructs a new node value.
242
- func newNode [T HamtValue [T ]](cs cbor.IpldStore , hashFn HashFunc , bitWidth int , zeroValue T ) * Node [T ] {
240
+ func newNode [T HamtValue [T ]](cs cbor.IpldStore , hashFn HashFunc , bitWidth int ) * Node [T ] {
243
241
nd := & Node [T ]{
244
- Bitfield : big .NewInt (0 ),
245
- Pointers : make ([]* Pointer [T ], 0 ),
246
- bitWidth : bitWidth ,
247
- hash : hashFn ,
248
- store : cs ,
249
- zeroValue : zeroValue ,
242
+ Bitfield : big .NewInt (0 ),
243
+ Pointers : make ([]* Pointer [T ], 0 ),
244
+ bitWidth : bitWidth ,
245
+ hash : hashFn ,
246
+ store : cs ,
250
247
}
251
248
return nd
252
249
}
@@ -281,7 +278,7 @@ func (n *Node[T]) getValue(ctx context.Context, hv *hashBits, k string, cb func(
281
278
if c .isShard () {
282
279
// if isShard, we have a pointer to a child that we need to load and
283
280
// delegate our find operation to
284
- chnd , err := c .loadChild (ctx , n .store , n .bitWidth , n .hash , n . zeroValue )
281
+ chnd , err := c .loadChild (ctx , n .store , n .bitWidth , n .hash )
285
282
if err != nil {
286
283
return err
287
284
}
@@ -303,12 +300,12 @@ func (n *Node[T]) getValue(ctx context.Context, hv *hashBits, k string, cb func(
303
300
304
301
// load a HAMT node from the IpldStore and pass on the (assumed) parameters
305
302
// that are not stored with the node.
306
- func (p * Pointer [T ]) loadChild (ctx context.Context , ns cbor.IpldStore , bitWidth int , hash HashFunc , zeroValue T ) (* Node [T ], error ) {
303
+ func (p * Pointer [T ]) loadChild (ctx context.Context , ns cbor.IpldStore , bitWidth int , hash HashFunc ) (* Node [T ], error ) {
307
304
if p .cache != nil {
308
305
return p .cache , nil
309
306
}
310
307
311
- out , err := loadNode [T ](ctx , ns , p .Link , false , bitWidth , hash , zeroValue )
308
+ out , err := loadNode [T ](ctx , ns , p .Link , false , bitWidth , hash )
312
309
if err != nil {
313
310
return nil , err
314
311
}
@@ -319,8 +316,8 @@ func (p *Pointer[T]) loadChild(ctx context.Context, ns cbor.IpldStore, bitWidth
319
316
320
317
// load a HAMT node from the IpldStore passing on the (assumed) parameters
321
318
// that are not stored with the node and return all KVs of the child and its children.
322
- func (p * Pointer [T ]) loadChildKVs (ctx context.Context , ns cbor.IpldStore , bitWidth int , hash HashFunc , zeroValue T ) ([]* KV [T ], error ) {
323
- child , err := p .loadChild (ctx , ns , bitWidth , hash , zeroValue )
319
+ func (p * Pointer [T ]) loadChildKVs (ctx context.Context , ns cbor.IpldStore , bitWidth int , hash HashFunc ) ([]* KV [T ], error ) {
320
+ child , err := p .loadChild (ctx , ns , bitWidth , hash )
324
321
if err != nil {
325
322
return nil , err
326
323
}
@@ -355,7 +352,7 @@ func LoadNode[T HamtValue[T]](ctx context.Context, cs cbor.IpldStore, c cid.Cid,
355
352
return nil , err
356
353
}
357
354
}
358
- return loadNode [T ](ctx , cs , c , true , cfg .bitWidth , cfg .hashFn , zero [ T ]() )
355
+ return loadNode [T ](ctx , cs , c , true , cfg .bitWidth , cfg .hashFn )
359
356
}
360
357
361
358
// internal version of loadNode that is aware of whether this is a root node or
@@ -367,7 +364,6 @@ func loadNode[T HamtValue[T]](
367
364
isRoot bool ,
368
365
bitWidth int ,
369
366
hashFunction HashFunc ,
370
- zeroValue T ,
371
367
) (* Node [T ], error ) {
372
368
var out Node [T ]
373
369
if err := cs .Get (ctx , c , & out ); err != nil {
@@ -377,7 +373,6 @@ func loadNode[T HamtValue[T]](
377
373
out .store = cs
378
374
out .bitWidth = bitWidth
379
375
out .hash = hashFunction
380
- out .zeroValue = zeroValue
381
376
382
377
// Validation
383
378
@@ -457,7 +452,7 @@ func (n *Node[T]) checkSize(ctx context.Context) (uint64, error) {
457
452
totsize := uint64 (buf .Len ())
458
453
for _ , ch := range n .Pointers {
459
454
if ch .isShard () {
460
- chnd , err := ch .loadChild (ctx , n .store , n .bitWidth , n .hash , n . zeroValue )
455
+ chnd , err := ch .loadChild (ctx , n .store , n .bitWidth , n .hash )
461
456
if err != nil {
462
457
return 0 , err
463
458
}
@@ -533,7 +528,7 @@ func (n *Node[T]) Flush(ctx context.Context) error {
533
528
// and save the resulting CID wherever you expect the HAMT root to persist.
534
529
func (n * Node [T ]) Set (ctx context.Context , k string , v T ) error {
535
530
keyBytes := []byte (k )
536
- _ , err := n .modifyValue (ctx , & hashBits {b : n .hash (keyBytes )}, keyBytes , v , OVERWRITE )
531
+ _ , err := n .modifyValue (ctx , & hashBits {b : n .hash (keyBytes )}, keyBytes , v , false , OVERWRITE )
537
532
return err
538
533
}
539
534
@@ -542,7 +537,7 @@ func (n *Node[T]) Set(ctx context.Context, k string, v T) error {
542
537
// false otherwise.
543
538
func (n * Node [T ]) SetIfAbsent (ctx context.Context , k string , v T ) (bool , error ) {
544
539
keyBytes := []byte (k )
545
- modified , err := n .modifyValue (ctx , & hashBits {b : n .hash (keyBytes )}, keyBytes , v , NOVERWRITE )
540
+ modified , err := n .modifyValue (ctx , & hashBits {b : n .hash (keyBytes )}, keyBytes , v , false , NOVERWRITE )
546
541
return bool (modified ), err
547
542
}
548
543
@@ -626,7 +621,7 @@ func (n *Node[T]) cleanChild(chnd *Node[T], cindex byte) error {
626
621
// cleanNode()). Recursive calls use the same arguments on child nodes but
627
622
// note that `hv.Next()` is not idempotent. Each call will increment the number
628
623
// of bits chomped off the hash digest for this key.
629
- func (n * Node [T ]) modifyValue (ctx context.Context , hv * hashBits , k []byte , v T , replace overwrite ) (modified , error ) {
624
+ func (n * Node [T ]) modifyValue (ctx context.Context , hv * hashBits , k []byte , v T , delete bool , replace overwrite ) (modified , error ) {
630
625
idx , err := hv .Next (n .bitWidth )
631
626
if err != nil {
632
627
return UNMODIFIED , ErrMaxDepth
@@ -636,7 +631,7 @@ func (n *Node[T]) modifyValue(ctx context.Context, hv *hashBits, k []byte, v T,
636
631
// doesn't exist in the HAMT already and can insert it at the appropriate
637
632
// position.
638
633
if n .Bitfield .Bit (idx ) != 1 {
639
- if n . zeroValue . Equals ( v ) { // Delete absent key
634
+ if delete { // Delete absent key
640
635
return UNMODIFIED , nil
641
636
}
642
637
return MODIFIED , n .insertKV (idx , k , v )
@@ -656,12 +651,12 @@ func (n *Node[T]) modifyValue(ctx context.Context, hv *hashBits, k []byte, v T,
656
651
// it is an eventual Flush passing back over this "cache" node which
657
652
// causes the updates made to the in-memory "cache" node to eventually
658
653
// be persisted.
659
- chnd , err := child .loadChild (ctx , n .store , n .bitWidth , n .hash , n . zeroValue )
654
+ chnd , err := child .loadChild (ctx , n .store , n .bitWidth , n .hash )
660
655
if err != nil {
661
656
return UNMODIFIED , err
662
657
}
663
658
664
- modified , err := chnd .modifyValue (ctx , hv , k , v , replace )
659
+ modified , err := chnd .modifyValue (ctx , hv , k , v , delete , replace )
665
660
if err != nil {
666
661
return UNMODIFIED , err
667
662
}
@@ -676,7 +671,7 @@ func (n *Node[T]) modifyValue(ctx context.Context, hv *hashBits, k []byte, v T,
676
671
// current data it contains. This may involve collapsing child nodes if
677
672
// they no longer contain enough elements to justify their stand-alone
678
673
// existence.
679
- if n . zeroValue . Equals ( v ) {
674
+ if delete {
680
675
if err := n .cleanChild (chnd , cindex ); err != nil {
681
676
return UNMODIFIED , err
682
677
}
@@ -689,7 +684,7 @@ func (n *Node[T]) modifyValue(ctx context.Context, hv *hashBits, k []byte, v T,
689
684
// modified (or deleted) here or needs to be added as a new child node if
690
685
// there is an overflow.
691
686
692
- if n . zeroValue . Equals ( v ) {
687
+ if delete {
693
688
// delete operation, find the child and remove it, compacting the bucket in
694
689
// the process
695
690
for i , p := range child .KVs {
@@ -721,15 +716,15 @@ func (n *Node[T]) modifyValue(ctx context.Context, hv *hashBits, k []byte, v T,
721
716
if len (child .KVs ) >= bucketSize {
722
717
// bucket is full, create a child node (shard) with all existing bucket
723
718
// elements plus the new one and set it in the place of the bucket
724
- sub := newNode [T ](n .store , n .hash , n .bitWidth , n . zeroValue )
719
+ sub := newNode [T ](n .store , n .hash , n .bitWidth )
725
720
hvcopy := & hashBits {b : hv .b , consumed : hv .consumed }
726
- if _ , err := sub .modifyValue (ctx , hvcopy , k , v , replace ); err != nil {
721
+ if _ , err := sub .modifyValue (ctx , hvcopy , k , v , delete , replace ); err != nil {
727
722
return UNMODIFIED , err
728
723
}
729
724
730
725
for _ , p := range child .KVs {
731
726
chhv := & hashBits {b : n .hash (p .Key ), consumed : hv .consumed }
732
- if _ , err := sub .modifyValue (ctx , chhv , p .Key , p .Value , replace ); err != nil {
727
+ if _ , err := sub .modifyValue (ctx , chhv , p .Key , p .Value , delete , replace ); err != nil {
733
728
return UNMODIFIED , err
734
729
}
735
730
}
@@ -802,7 +797,7 @@ func (n *Node[T]) getPointer(i byte) *Pointer[T] {
802
797
// as cached nodes.
803
798
func (n * Node [T ]) Copy () * Node [T ] {
804
799
// TODO(rvagg): clarify what situations this method is actually useful for.
805
- nn := newNode [T ](n .store , n .hash , n .bitWidth , n . zeroValue )
800
+ nn := newNode [T ](n .store , n .hash , n .bitWidth )
806
801
nn .Bitfield .Set (n .Bitfield )
807
802
nn .Pointers = make ([]* Pointer [T ], len (n .Pointers ))
808
803
@@ -838,7 +833,7 @@ func (p *Pointer[T]) isShard() bool {
838
833
func (n * Node [T ]) ForEach (ctx context.Context , f func (k string , val T ) error ) error {
839
834
for _ , p := range n .Pointers {
840
835
if p .isShard () {
841
- chnd , err := p .loadChild (ctx , n .store , n .bitWidth , n .hash , n . zeroValue )
836
+ chnd , err := p .loadChild (ctx , n .store , n .bitWidth , n .hash )
842
837
if err != nil {
843
838
return err
844
839
}
0 commit comments