Commit 23aec76e authored by Eric Myhre's avatar Eric Myhre

Extract the interface for declaring a node to be self-tokenizing.

Signed-off-by: default avatarEric Myhre <hash@exultant.us>
parent 4e3c8def
...@@ -32,8 +32,13 @@ func (n *Node) PushTokens(sink shared.TokenSink) error { ...@@ -32,8 +32,13 @@ func (n *Node) PushTokens(sink shared.TokenSink) error {
if _, err := sink.Step(&tk); err != nil { if _, err := sink.Step(&tk); err != nil {
return err return err
} }
if err := v.PushTokens(sink); err != nil { switch v2 := v.(type) {
return err case ipld.TokenizableNode:
if err := v2.PushTokens(sink); err != nil {
return err
}
default:
panic("todo generic node tokenizer fallback")
} }
} }
// Emit map close. // Emit map close.
...@@ -49,8 +54,13 @@ func (n *Node) PushTokens(sink shared.TokenSink) error { ...@@ -49,8 +54,13 @@ func (n *Node) PushTokens(sink shared.TokenSink) error {
} }
// Emit list contents (and recurse). // Emit list contents (and recurse).
for _, v := range n._arr { for _, v := range n._arr {
if err := v.PushTokens(sink); err != nil { switch v2 := v.(type) {
return err case ipld.TokenizableNode:
if err := v2.PushTokens(sink); err != nil {
return err
}
default:
panic("todo generic node tokenizer fallback")
} }
} }
// Emit list close. // Emit list close.
......
package ipld package ipld
import ( import (
"github.com/polydawn/refmt/shared"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
) )
...@@ -57,13 +55,6 @@ type Node interface { ...@@ -57,13 +55,6 @@ type Node interface {
AsString() (string, error) AsString() (string, error)
AsBytes() ([]byte, error) AsBytes() ([]byte, error)
AsLink() (cid.Cid, error) AsLink() (cid.Cid, error)
// PushTokens converts this node and its children into a stream of refmt Tokens
// and push them sequentially into the given TokenSink.
// This is useful for serializing, or hashing, or feeding to any other
// TokenSink (for example, converting to other ipld.Node implementations
// which can construct themselves from a token stream).
PushTokens(sink shared.TokenSink) error
} }
type SerializableNode interface { type SerializableNode interface {
......
package ipld
import (
"github.com/polydawn/refmt/shared"
)
// TokenizableNode is an optional interface which an ipld.Node may also
// implement to indicate that it has an efficient method for translating
// itself to a serial Token stream.
//
// Any ipld.Node is tokenizable via generic inspection, so providing
// this interface is optional and purely for performance improvement.
type TokenizableNode interface {
// PushTokens converts this node and its children into a stream of refmt Tokens
// and push them sequentially into the given TokenSink.
// This is useful for serializing, or hashing, or feeding to any other
// TokenSink (for example, converting to other ipld.Node implementations
// which can construct themselves from a token stream).
PushTokens(sink shared.TokenSink) error
}
...@@ -5,6 +5,8 @@ import ( ...@@ -5,6 +5,8 @@ import (
"github.com/polydawn/refmt/tok" "github.com/polydawn/refmt/tok"
. "github.com/warpfork/go-wish" . "github.com/warpfork/go-wish"
"github.com/ipld/go-ipld-prime"
) )
// TokenBucket acts as a TokenSink; you can dump data into it and then // TokenBucket acts as a TokenSink; you can dump data into it and then
...@@ -55,7 +57,7 @@ func TestScalarMarshal(t *testing.T, newNode MutableNodeFactory) { ...@@ -55,7 +57,7 @@ func TestScalarMarshal(t *testing.T, newNode MutableNodeFactory) {
n0 := newNode() n0 := newNode()
n0.SetNull() n0.SetNull()
var tb TokenBucket var tb TokenBucket
n0.PushTokens(&tb) (n0.(ipld.TokenizableNode)).PushTokens(&tb)
Wish(t, tb, ShouldEqual, TokenBucket{ Wish(t, tb, ShouldEqual, TokenBucket{
{Type: tok.TNull}, {Type: tok.TNull},
}) })
...@@ -69,7 +71,7 @@ func TestRecursiveMarshal(t *testing.T, newNode MutableNodeFactory) { ...@@ -69,7 +71,7 @@ func TestRecursiveMarshal(t *testing.T, newNode MutableNodeFactory) {
n00.SetString("asdf") n00.SetString("asdf")
n0.SetIndex(0, n00) n0.SetIndex(0, n00)
var tb TokenBucket var tb TokenBucket
n0.PushTokens(&tb) (n0.(ipld.TokenizableNode)).PushTokens(&tb)
Wish(t, tb.Minimalize(), ShouldEqual, TokenBucket{ Wish(t, tb.Minimalize(), ShouldEqual, TokenBucket{
{Type: tok.TArrOpen, Length: 1}, {Type: tok.TArrOpen, Length: 1},
{Type: tok.TString, Str: "asdf"}, {Type: tok.TString, Str: "asdf"},
...@@ -87,7 +89,7 @@ func TestRecursiveMarshal(t *testing.T, newNode MutableNodeFactory) { ...@@ -87,7 +89,7 @@ func TestRecursiveMarshal(t *testing.T, newNode MutableNodeFactory) {
n01.SetString("quux") n01.SetString("quux")
n0.SetIndex(1, n01) n0.SetIndex(1, n01)
var tb TokenBucket var tb TokenBucket
n0.PushTokens(&tb) (n0.(ipld.TokenizableNode)).PushTokens(&tb)
Wish(t, tb.Minimalize(), ShouldEqual, TokenBucket{ Wish(t, tb.Minimalize(), ShouldEqual, TokenBucket{
{Type: tok.TArrOpen, Length: 2}, {Type: tok.TArrOpen, Length: 2},
{Type: tok.TArrOpen, Length: 1}, {Type: tok.TArrOpen, Length: 1},
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment