56 lines
2.0 KiB
Go
56 lines
2.0 KiB
Go
|
package state
|
||
|
|
||
|
import (
|
||
|
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||
|
typegen "github.com/whyrusleeping/cbor-gen"
|
||
|
)
|
||
|
|
||
|
// AdtArrayDiff generalizes adt.Array diffing by accepting a Deferred type that can unmarshalled to its corresponding struct
|
||
|
// in an interface implantation.
|
||
|
// Add should be called when a new k,v is added to the array
|
||
|
// Modify should be called when a value is modified in the array
|
||
|
// Remove should be called when a value is removed from the array
|
||
|
type AdtArrayDiff interface {
|
||
|
Add(val *typegen.Deferred) error
|
||
|
Modify(from, to *typegen.Deferred) error
|
||
|
Remove(val *typegen.Deferred) error
|
||
|
}
|
||
|
|
||
|
// TODO Performance can be improved by diffing the underlying IPLD graph, e.g. https://github.com/ipfs/go-merkledag/blob/749fd8717d46b4f34c9ce08253070079c89bc56d/dagutils/diff.go#L104
|
||
|
// CBOR Marshaling will likely be the largest performance bottleneck here.
|
||
|
|
||
|
// DiffAdtArray accepts two *adt.Array's and an AdtArrayDiff implementation. It does the following:
|
||
|
// - All values that exist in preArr and not in curArr are passed to AdtArrayDiff.Remove()
|
||
|
// - All values that exist in curArr nnd not in prevArr are passed to adtArrayDiff.Add()
|
||
|
// - All values that exist in preArr and in curArr are passed to AdtArrayDiff.Modify()
|
||
|
// - It is the responsibility of AdtArrayDiff.Modify() to determine if the values it was passed have been modified.
|
||
|
func DiffAdtArray(preArr, curArr *adt.Array, out AdtArrayDiff) error {
|
||
|
prevVal := new(typegen.Deferred)
|
||
|
if err := preArr.ForEach(prevVal, func(i int64) error {
|
||
|
curVal := new(typegen.Deferred)
|
||
|
found, err := curArr.Get(uint64(i), curVal)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if !found {
|
||
|
if err := out.Remove(prevVal); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
if err := out.Modify(prevVal, curVal); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return curArr.Delete(uint64(i))
|
||
|
}); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
curVal := new(typegen.Deferred)
|
||
|
return curArr.ForEach(curVal, func(i int64) error {
|
||
|
return out.Add(curVal)
|
||
|
})
|
||
|
}
|