Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: map/list interfaces #451

Closed
wants to merge 13 commits into from
8 changes: 8 additions & 0 deletions datamodel/container.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package datamodel

type Container interface {
Empty() bool
Length() int64
Clear()
Values() []Node
}
11 changes: 11 additions & 0 deletions datamodel/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package datamodel

type List interface {
Get(idx int64) (Node, bool)
Remove(idx int64)
Append(values ...interface{})
Insert(idx int64, values ...interface{})
Set(idx int64, value interface{})

Container
}
10 changes: 10 additions & 0 deletions datamodel/map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package datamodel

type Map interface {
Put(key string, value interface{}) bool
Get(key string) (value Node, found bool)
Remove(key string) bool
Keys() []string

Container
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/ipld/go-ipld-prime
go 1.17

require (
github.com/emirpasic/gods v1.18.1
github.com/frankban/quicktest v1.14.3
github.com/google/go-cmp v0.5.8
github.com/ipfs/go-cid v0.2.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
Expand Down
1 change: 1 addition & 0 deletions storage/benchmarks/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
Expand Down
129 changes: 129 additions & 0 deletions traversal/amendAny.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package traversal

import "github.com/ipld/go-ipld-prime/datamodel"

var (
_ datamodel.Node = &anyAmender{}
_ Amender = &anyAmender{}
)

type anyAmender struct {
amendCfg
}

func (opts AmendOptions) newAnyAmender(base datamodel.Node, parent Amender, create bool) Amender {
// If the base node is already an any-amender, reuse it but reset `parent` and `created`.
if amd, castOk := base.(*anyAmender); castOk {
return &anyAmender{amendCfg{&opts, amd.base, parent, create}}
} else {
return &anyAmender{amendCfg{&opts, base, parent, create}}
}
}

// -- Node -->

func (a *anyAmender) Kind() datamodel.Kind {
return a.base.Kind()
}

func (a *anyAmender) LookupByString(key string) (datamodel.Node, error) {
return a.base.LookupByString(key)
}

func (a *anyAmender) LookupByNode(key datamodel.Node) (datamodel.Node, error) {
return a.base.LookupByNode(key)
}

func (a *anyAmender) LookupByIndex(idx int64) (datamodel.Node, error) {
return a.base.LookupByIndex(idx)
}

func (a *anyAmender) LookupBySegment(seg datamodel.PathSegment) (datamodel.Node, error) {
return a.base.LookupBySegment(seg)
}

func (a *anyAmender) MapIterator() datamodel.MapIterator {
return a.base.MapIterator()
}

func (a *anyAmender) ListIterator() datamodel.ListIterator {
return a.base.ListIterator()
}

func (a *anyAmender) Length() int64 {
return a.base.Length()
}

func (a *anyAmender) IsAbsent() bool {
return a.base.IsAbsent()
}

func (a *anyAmender) IsNull() bool {
return a.base.IsNull()
}

func (a *anyAmender) AsBool() (bool, error) {
return a.base.AsBool()
}

func (a *anyAmender) AsInt() (int64, error) {
return a.base.AsInt()
}

func (a *anyAmender) AsFloat() (float64, error) {
return a.base.AsFloat()
}

func (a *anyAmender) AsString() (string, error) {
return a.base.AsString()
}

func (a *anyAmender) AsBytes() ([]byte, error) {
return a.base.AsBytes()
}

func (a *anyAmender) AsLink() (datamodel.Link, error) {
return a.base.AsLink()
}

func (a *anyAmender) Prototype() datamodel.NodePrototype {
return a.base.Prototype()
}

// -- Amender -->

func (a *anyAmender) Fetch(prog *Progress, path datamodel.Path, trackProgress bool) (datamodel.Node, error) {
// If the base node is an amender, use it, otherwise return the base node.
if amd, castOk := a.base.(Amender); castOk {
return amd.Fetch(prog, path, trackProgress)
}
return a.base, nil
}

func (a *anyAmender) Transform(prog *Progress, path datamodel.Path, fn TransformFn, createParents bool) (datamodel.Node, error) {
// Allow the base node to be replaced.
if path.Len() == 0 {
prevNode := a.Build()
if newNode, err := fn(*prog, prevNode); err != nil {
return nil, err
} else {
// Go through `newAnyAmender` in case `newNode` is already an any-amender.
*a = *a.opts.newAnyAmender(newNode, a.parent, a.created).(*anyAmender)
return prevNode, nil
}
}
// If the base node is an amender, use it, otherwise panic.
if amd, castOk := a.base.(Amender); castOk {
return amd.Transform(prog, path, fn, createParents)
}
panic("misuse")
}

func (a *anyAmender) Build() datamodel.Node {
// `anyAmender` is also a `Node`.
return (datamodel.Node)(a)
}

func (a *anyAmender) isCreated() bool {
return a.created
}
Loading