// swapValue sets the link `value` in the given key, either creating the entry
// if it didn't exist or overwriting the old one. It returns the old entry (if any).
swapValue sets the link `value` in the given key, either creating the entry
if it didn't exist or overwriting the old one. It returns the old entry (if any).
// swapValue sets the link ` value ` in the given key either creating the entry // if it didn ' t exist or overwriting the old one . It returns the old entry ( if any ) .
func (ds *Shard) swapValue(ctx context.Context, hv *hashBits, key string, value *ipld.Link) (*ipld.Link, error) {
	idx, err := hv.Next(ds.tableSizeLg2)
	if err != nil {
		return nil, err
	}
	if !ds.childer.has(idx) {
		return nil, ds.childer.insert(key, value, idx)
	}
	i := ds.childer.sliceIndex(idx)
	child, err := ds.childer.get(ctx, i)
	if err != nil {
		return nil, err
	}
	if child.isValueNode() {
		if child.key == key {
			oldValue := child.val
			if value == nil { 
				return oldValue, ds.childer.rm(idx)
			}
			child.val = value 
			return oldValue, nil
		}
		if value == nil {
			return nil, os.ErrNotExist
		}
		grandChild := child
		child, err = NewShard(ds.dserv, ds.tableSize)
		if err != nil {
			return nil, err
		}
		child.builder = ds.builder
		chhv := newConsumedHashBits(grandChild.key, hv.consumed)
		_, err = child.swapValue(ctx, hv, key, value)
		if err != nil {
			return nil, err
		}
		_, err = child.swapValue(ctx, chhv, grandChild.key, grandChild.val)
		if err != nil {
			return nil, err
		}
		ds.childer.set(child, i)
		return nil, nil
	} else {
		oldValue, err := child.swapValue(ctx, hv, key, value)
		if err != nil {
			return nil, err
		}
		if value == nil {
			switch child.childer.length() {
			case 0:
				return oldValue, ds.childer.rm(idx)
			case 1:
				schild := child.childer.child(0)
				if schild != nil {
					if schild.isValueNode() {
						ds.childer.set(schild, i)
					}
					return oldValue, nil
				}
				slnk := child.childer.link(0)
				var lnkType linkType
				lnkType, err = child.childer.sd.childLinkType(slnk)
				if err != nil {
					return nil, err
				}
				if lnkType == shardValueLink {
					ds.childer.setLink(slnk, i)
				}
				return oldValue, nil
			}
		}
		return oldValue, nil
	}
}
func ( ds * Shard ) swapValue ( ctx context . Context , hv * hashBits , key string , value * ipld . Link ) ( * ipld . Link , error ) { idx , err := hv . Next ( ds . tableSizeLg2 ) if err != nil { return nil , err } if ! ds . childer . has ( idx ) { return nil , ds . childer . insert ( key , value , idx ) } i := ds . childer . sliceIndex ( idx ) child , err := ds . childer . get ( ctx , i ) if err != nil { return nil , err } if child . isValueNode ( ) { if child . key == key { oldValue := child . val if value == nil { return oldValue , ds . childer . rm ( idx ) } child . val = value return oldValue , nil } if value == nil { return nil , os . ErrNotExist } grandChild := child child , err = NewShard ( ds . dserv , ds . tableSize ) if err != nil { return nil , err } child . builder = ds . builder chhv := newConsumedHashBits ( grandChild . key , hv . consumed ) _ , err = child . swapValue ( ctx , hv , key , value ) if err != nil { return nil , err } _ , err = child . swapValue ( ctx , chhv , grandChild . key , grandChild . val ) if err != nil { return nil , err } ds . childer . set ( child , i ) return nil , nil } else { oldValue , err := child . swapValue ( ctx , hv , key , value ) if err != nil { return nil , err } if value == nil { switch child . childer . length ( ) { case 0 : return oldValue , ds . childer . rm ( idx ) case 1 : schild := child . childer . child ( 0 ) if schild != nil { if schild . isValueNode ( ) { ds . childer . set ( schild , i ) } return oldValue , nil } slnk := child . childer . link ( 0 ) var lnkType linkType lnkType , err = child . childer . sd . childLinkType ( slnk ) if err != nil { return nil , err } if lnkType == shardValueLink { ds . childer . setLink ( slnk , i ) } return oldValue , nil } } return oldValue , nil } }
swapValue sets the link `value` in the given key, either creating the entry
if it didn't exist or overwriting the old one.
swapValue sets the link ` value ` in the given key either creating the entry if it didn ' t exist or overwriting the old one .
// Entry does not exist, create a new one. // Leaf node. This is the base case of this recursive function. // We are in the correct shard (tree level) so we modify this child // and return. // Remove old entry. // Overwrite entry. // We are in the same slot with another entry with a different key // so we need to fork this leaf node into a shard with two childs: // the old entry and the new one being inserted here. // We don't overwrite anything here so we keep: //   `oldValue = nil` // The child of this shard will now be a new shard. The old child value // will be a child of this new shard (along with the new value being // inserted). // We explicitly ignore the oldValue returned by the next two insertions // (which will be nil) to highlight there is no overwrite here: they are // done with different keys to a new (empty) shard. (At best this shard // will create new ones until we find different slots for both.) // Replace this leaf node with the new Shard node. // We are in a Shard (internal node). We will recursively call this // function until finding the leaf (the logic of the `if` case above). // We have removed an entry, check if we should remove shards // as well. // empty sub-shard, prune it // Note: this shouldnt normally ever happen //       in the event of another implementation creates flawed //       structures, this will help to normalize them. // The single child _should_ be a value by // induction. However, we allow for it to be a // shard in case an implementation is broken. // Have we loaded the child? Prefer that. // Otherwise, work with the link. // sub-shard with a single value element, collapse it