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

Addtional examples of bindnode usage. #209

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions node/bindnode/example_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package bindnode_test

import (
"bytes"
"fmt"
"os"

ipld "github.com/ipld/go-ipld-prime"
Expand Down Expand Up @@ -80,3 +82,104 @@ func ExamplePrototype_onlySchema() {
// Output:
// {"Friends":["Sarah","Alex"],"Name":"Michael"}
}

func ExampleWrap_withSchemaUsingStringjoinStruct() {
ts := schema.TypeSystem{}
ts.Init()
ts.Accumulate(schema.SpawnString("String"))
ts.Accumulate(schema.SpawnStruct("FooBarBaz",
[]schema.StructField{
schema.SpawnStructField("foo", "String", false, false),
schema.SpawnStructField("bar", "String", false, false),
schema.SpawnStructField("baz", "String", false, false),
},
schema.SpawnStructRepresentationStringjoin(":"),
))
schemaType := ts.TypeByName("FooBarBaz")

type FooBarBaz struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this mapping working? Does it just use field order to figure out what to assign where? So the schema could have any arbitrary name but the values get assigned to whatever order is there?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, when mapping a provided IPLD schema with a provided Go type, it just cares about the "shape" matching, not any names. For a struct, that means that the fields should have matching types in the same order.

Doing the mapping via names or struct field tags would also be an option, though it would require more code and features, so I initially just went for the simplest approach from my point of view.

I haven't documented this, mind you, because I'm not 100% certain that this default behavior is right. I think most users would expect case-insensitive-matching by field name, similar to most other Go libraries. I'm not bothered by this example being public, but the semantics in this case might change.

Foo string
Bar string
Baz string
}
fbb := &FooBarBaz{
Foo: "x",
Bar: "y",
Baz: "z",
}
node := bindnode.Wrap(fbb, schemaType)

// Take the representation of the node, and serialize it.
nodeRepr := node.Representation()
var buf bytes.Buffer
dagjson.Encode(nodeRepr, &buf)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check error?


// Output how this was serialized, for the example.
fmt.Fprintf(os.Stdout, "json: %s\n", buf.Bytes())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for the sake of keeping the example simpler, you could just dagjson.Encode straight to os.Stdout, printing json: in the line above or in the same line via Printf


// Now unmarshal that again and print that too, to show it working both ways.
np := bindnode.Prototype(&FooBarBaz{}, schemaType)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you could just do node.Prototype() here, unless you want to showcase bindnode.Prototype too

nb := np.Representation().NewBuilder()
err := dagjson.Decode(nb, &buf)
if err != nil {
panic(err)
}
fmt.Printf("golang: %#v\n", bindnode.Unwrap(nb.Build()))

// Output:
// json: "x:y:z"
// golang: &bindnode_test.FooBarBaz{Foo:"x", Bar:"y", Baz:"z"}
}

func ExampleWrap_withSchemaUsingStringprefixUnion() {
ts := schema.TypeSystem{}
ts.Init()
ts.Accumulate(schema.SpawnString("Foo"))
ts.Accumulate(schema.SpawnString("Bar"))
ts.Accumulate(schema.SpawnUnion("FooOrBar",
[]schema.TypeName{
"Foo",
"Bar",
},
schema.SpawnUnionRepresentationStringprefix(
":", // n.b. this API will change soon; a schema-schema iteration has removed the distinct joiner string.
map[string]schema.TypeName{
"foo": "Foo",
"bar": "Bar",
},
),
))
schemaType := ts.TypeByName("FooOrBar")

// The golang structures for unions don't look as simple as one might like. Golang has no native sum types, so we do something interesting here.
type FooOrBar struct {
Index int
Value interface{}
}
fob := &FooOrBar{
Index: 1,
Value: "oi",
}
node := bindnode.Wrap(fob, schemaType)

// Take the representation of the node, and serialize it.
nodeRepr := node.Representation()
var buf bytes.Buffer
dagjson.Encode(nodeRepr, &buf)

// Output how this was serialized, for the example.
fmt.Fprintf(os.Stdout, "json: %s\n", buf.Bytes())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comments as in the other example: error and buffer :)


// Now unmarshal that again and print that too, to show it working both ways.
np := bindnode.Prototype((*FooOrBar)(nil), schemaType)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: in one example you use &T{}, and in the other you use (*T)(nil). the latter is slightly better, as it avoids an alloc. but you should also be consistent.

nb := np.Representation().NewBuilder()
err := dagjson.Decode(nb, &buf)
if err != nil {
panic(err)
}
fmt.Printf("golang: %#v\n", bindnode.Unwrap(nb.Build()))

// Output:
// json: "bar:oi"
// golang: &bindnode_test.FooOrBar{Index:1, Value:"oi"}
}