Skip to content

Commit

Permalink
feat!: use generics instead of cbg.Deferred
Browse files Browse the repository at this point in the history
  • Loading branch information
rvagg committed Aug 2, 2024
1 parent 361416e commit d2712ad
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 377 deletions.
32 changes: 18 additions & 14 deletions cbor_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"io"
"math/big"
"reflect"

cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
Expand All @@ -18,7 +19,7 @@ var _ = xerrors.Errorf

var lengthBufNode = []byte{130}

func (t *Node) MarshalCBOR(w io.Writer) error {
func (t *Node[T]) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
Expand Down Expand Up @@ -57,13 +58,12 @@ func (t *Node) MarshalCBOR(w io.Writer) error {
if err := v.MarshalCBOR(cw); err != nil {
return err
}

}
return nil
}

func (t *Node) UnmarshalCBOR(r io.Reader) (err error) {
*t = Node{}
func (t *Node[T]) UnmarshalCBOR(r io.Reader) (err error) {
*t = Node[T]{}

cr := cbg.NewCborReader(r)

Expand Down Expand Up @@ -125,12 +125,12 @@ func (t *Node) UnmarshalCBOR(r io.Reader) (err error) {
}

if extra > 0 {
t.Pointers = make([]*Pointer, extra)
t.Pointers = make([]*Pointer[T], extra)
}

for i := 0; i < int(extra); i++ {

var v Pointer
var v Pointer[T]
if err := v.UnmarshalCBOR(cr); err != nil {
return err
}
Expand All @@ -143,7 +143,7 @@ func (t *Node) UnmarshalCBOR(r io.Reader) (err error) {

var lengthBufKV = []byte{130}

func (t *KV) MarshalCBOR(w io.Writer) error {
func (t *KV[T]) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
Expand All @@ -168,15 +168,15 @@ func (t *KV) MarshalCBOR(w io.Writer) error {
return err
}

// t.Value (typegen.Deferred) (struct)
// t.Value (T) (struct)
if err := t.Value.MarshalCBOR(cw); err != nil {
return err
}
return nil
}

func (t *KV) UnmarshalCBOR(r io.Reader) (err error) {
*t = KV{}
func (t *KV[T]) UnmarshalCBOR(r io.Reader) (err error) {
*t = KV[T]{}

cr := cbg.NewCborReader(r)

Expand Down Expand Up @@ -220,15 +220,19 @@ func (t *KV) UnmarshalCBOR(r io.Reader) (err error) {
return err
}

// t.Value (typegen.Deferred) (struct)
// t.Value (T) (struct)

{

t.Value = new(cbg.Deferred)
valueType := reflect.TypeOf(t.Value).Elem()
value := reflect.New(valueType).Interface().(T)

if err := t.Value.UnmarshalCBOR(cr); err != nil {
return xerrors.Errorf("failed to read deferred field: %w", err)
if err := value.UnmarshalCBOR(cr); err != nil {
return xerrors.Errorf("failed to read field: %w", err)
}

t.Value = value

}
return nil
}
68 changes: 33 additions & 35 deletions diff.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package hamt

import (
"bytes"
"context"
"encoding/json"

"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
)

Expand All @@ -23,30 +21,30 @@ const (

// Change represents a change to a DAG and contains a reference to the old and
// new CIDs.
type Change struct {
type Change[T HamtValue[T]] struct {
Type ChangeType
Key string
Before *cbg.Deferred
After *cbg.Deferred
Before *T
After *T
}

func (ch Change) String() string {
func (ch Change[T]) String() string {
b, _ := json.Marshal(ch)
return string(b)
}

// Diff returns a set of changes that transform node 'prev' into node 'cur'. opts are applied to both prev and cur.
func Diff(ctx context.Context, prevBs, curBs cbor.IpldStore, prev, cur cid.Cid, opts ...Option) ([]*Change, error) {
func Diff[T HamtValue[T]](ctx context.Context, prevBs, curBs cbor.IpldStore, prev, cur cid.Cid, opts ...Option) ([]*Change[T], error) {
if prev.Equals(cur) {
return nil, nil
}

prevHamt, err := LoadNode(ctx, prevBs, prev, opts...)
prevHamt, err := LoadNode[T](ctx, prevBs, prev, opts...)
if err != nil {
return nil, err
}

curHamt, err := LoadNode(ctx, curBs, cur, opts...)
curHamt, err := LoadNode[T](ctx, curBs, cur, opts...)
if err != nil {
return nil, err
}
Expand All @@ -57,7 +55,7 @@ func Diff(ctx context.Context, prevBs, curBs cbor.IpldStore, prev, cur cid.Cid,
return diffNode(ctx, prevHamt, curHamt, 0)
}

func diffNode(ctx context.Context, pre, cur *Node, depth int) ([]*Change, error) {
func diffNode[T HamtValue[T]](ctx context.Context, pre, cur *Node[T], depth int) ([]*Change[T], error) {
// which Bitfield contains the most bits. We will start a loop from this index, calling Bitfield.Bit(idx)
// on an out of range index will return zero.
bp := cur.Bitfield.BitLen()
Expand All @@ -66,7 +64,7 @@ func diffNode(ctx context.Context, pre, cur *Node, depth int) ([]*Change, error)
}

// the changes between cur and prev
var changes []*Change
var changes []*Change[T]

// loop over each bit in the bitfields
for idx := bp; idx >= 0; idx-- {
Expand Down Expand Up @@ -138,10 +136,10 @@ func diffNode(ctx context.Context, pre, cur *Node, depth int) ([]*Change, error)
changes = append(changes, rm...)
} else {
for _, p := range pointer.KVs {
changes = append(changes, &Change{
changes = append(changes, &Change[T]{
Type: Remove,
Key: string(p.Key),
Before: p.Value,
Before: &p.Value,
After: nil,
})
}
Expand All @@ -162,11 +160,11 @@ func diffNode(ctx context.Context, pre, cur *Node, depth int) ([]*Change, error)
changes = append(changes, add...)
} else {
for _, p := range pointer.KVs {
changes = append(changes, &Change{
changes = append(changes, &Change[T]{
Type: Add,
Key: string(p.Key),
Before: nil,
After: p.Value,
After: &p.Value,
})
}
}
Expand All @@ -176,21 +174,21 @@ func diffNode(ctx context.Context, pre, cur *Node, depth int) ([]*Change, error)
return changes, nil
}

func diffKVs(pre, cur []*KV, idx int) []*Change {
preMap := make(map[string]*cbg.Deferred, len(pre))
curMap := make(map[string]*cbg.Deferred, len(cur))
var changes []*Change
func diffKVs[T HamtValue[T]](pre, cur []*KV[T], idx int) []*Change[T] {
preMap := make(map[string]*T, len(pre))
curMap := make(map[string]*T, len(cur))
var changes []*Change[T]

for _, kv := range pre {
preMap[string(kv.Key)] = kv.Value
preMap[string(kv.Key)] = &kv.Value
}
for _, kv := range cur {
curMap[string(kv.Key)] = kv.Value
curMap[string(kv.Key)] = &kv.Value
}
// find removed keys: keys in pre and not in cur
for key, value := range preMap {
if _, ok := curMap[key]; !ok {
changes = append(changes, &Change{
changes = append(changes, &Change[T]{
Type: Remove,
Key: key,
Before: value,
Expand All @@ -202,15 +200,15 @@ func diffKVs(pre, cur []*KV, idx int) []*Change {
// find modified values: keys in cur and pre with different values
for key, curVal := range curMap {
if preVal, ok := preMap[key]; !ok {
changes = append(changes, &Change{
changes = append(changes, &Change[T]{
Type: Add,
Key: key,
Before: nil,
After: curVal,
})
} else {
if !bytes.Equal(preVal.Raw, curVal.Raw) {
changes = append(changes, &Change{
if !(*preVal).Equal(*curVal) {
changes = append(changes, &Change[T]{
Type: Modify,
Key: key,
Before: preVal,
Expand All @@ -222,14 +220,14 @@ func diffKVs(pre, cur []*KV, idx int) []*Change {
return changes
}

func addAll(ctx context.Context, node *Node, idx int) ([]*Change, error) {
var changes []*Change
if err := node.ForEach(ctx, func(k string, val *cbg.Deferred) error {
changes = append(changes, &Change{
func addAll[T HamtValue[T]](ctx context.Context, node *Node[T], idx int) ([]*Change[T], error) {
var changes []*Change[T]
if err := node.ForEach(ctx, func(k string, val T) error {
changes = append(changes, &Change[T]{
Type: Add,
Key: k,
Before: nil,
After: val,
After: &val,
})

return nil
Expand All @@ -239,13 +237,13 @@ func addAll(ctx context.Context, node *Node, idx int) ([]*Change, error) {
return changes, nil
}

func removeAll(ctx context.Context, node *Node, idx int) ([]*Change, error) {
var changes []*Change
if err := node.ForEach(ctx, func(k string, val *cbg.Deferred) error {
changes = append(changes, &Change{
func removeAll[T HamtValue[T]](ctx context.Context, node *Node[T], idx int) ([]*Change[T], error) {
var changes []*Change[T]
if err := node.ForEach(ctx, func(k string, val T) error {
changes = append(changes, &Change[T]{
Type: Remove,
Key: k,
Before: val,
Before: &val,
After: nil,
})

Expand Down
Loading

0 comments on commit d2712ad

Please sign in to comment.