Skip to content

Commit

Permalink
fix: rebind a typed node (#25)
Browse files Browse the repository at this point in the history
This PR allows `Rebind` to work on `schema.TypedNode`. This was a hidden
error because oftentimes the representation form is compatible with the
typed form. However when you start to use custom representations e.g.
tuple, then `Rebind` will not work, since the `datamodel.Node` will have
a map, when represented type expects a list.

The solution is to simply convert a `TypedNode` to it's representation
form prior to binding to the type.

This is likely not used very often - if you have a _typed_ node then you
have/had it in it's native Go type at some point, so you shouldn't need
to rebind. This is however seen it tests, when a server is invoked by a
client without serializing/deserializing capability caveats - and the
validator has to parse already parsed caveats.
  • Loading branch information
alanshaw authored Oct 18, 2024
1 parent 0909684 commit 175193f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
4 changes: 4 additions & 0 deletions core/ipld/rebind.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ func Rebind[T any](nd datamodel.Node, typ schema.Type) (ptrVal T, err error) {
}
}()

if typedNode, ok := nd.(schema.TypedNode); ok {
nd = typedNode.Representation()
}

var nilbind T
np := bindnode.Prototype(&nilbind, typ)
nb := np.Representation().NewBuilder()
Expand Down
26 changes: 26 additions & 0 deletions core/ipld/rebind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/datamodel"
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
"github.com/ipld/go-ipld-prime/node/bindnode"
"github.com/storacha/go-ucanto/core/ipld/codec/cbor"
"github.com/stretchr/testify/require"
)

func TestRebind(t *testing.T) {
Expand Down Expand Up @@ -229,3 +231,27 @@ func TestRebindNonCompatibleSchema(t *testing.T) {
}
fmt.Println(err)
}

func TestRebindTypedNode(t *testing.T) {
type Target struct {
Astring string
Aint int
}

ts, err := ipld.LoadSchemaBytes([]byte(`
type Target struct {
astring String
aint Int
} representation tuple
`))
require.NoError(t, err)

typ := ts.TypeByName("Target")

target := Target{Astring: "hello", Aint: 1}
nd := bindnode.Wrap(&target, typ)

rebindTarget, err := Rebind[Target](nd, typ)
require.NoError(t, err)
fmt.Printf("%+v\n", rebindTarget)
}

0 comments on commit 175193f

Please sign in to comment.