-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into linksystem
Resolves conflicts in go.sum. (They were conflicts in a textual sense only, but semantically trivial; application of `go mod tidy` was sufficient.)
- Loading branch information
Showing
5 changed files
with
248 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Package raw implements IPLD's raw codec, which simply writes and reads a Node | ||
// which can be represented as bytes. | ||
// | ||
// The codec can be used with any node which supports AsBytes and AssignBytes. | ||
// In general, it only makes sense to use this codec on a plain "bytes" node | ||
// such as github.com/ipld/go-ipld-prime/node/basic.Prototype.Bytes. | ||
package raw | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
|
||
ipld "github.com/ipld/go-ipld-prime" | ||
cidlink "github.com/ipld/go-ipld-prime/linking/cid" | ||
) | ||
|
||
// TODO(mvdan): make go-ipld-prime use go-multicodec soon | ||
const rawMulticodec = 0x55 | ||
|
||
func init() { | ||
cidlink.RegisterMulticodecDecoder(rawMulticodec, Decode) | ||
cidlink.RegisterMulticodecEncoder(rawMulticodec, Encode) | ||
} | ||
|
||
// Decode implements decoding of a node with the raw codec. | ||
// | ||
// Note that if r has a Bytes method, such as is the case with *bytes.Buffer, we | ||
// will use those bytes directly to save having to allocate and copy them. The | ||
// Node interface is defined as immutable, so it is assumed that its bytes won't | ||
// be modified in-place. Similarly, we assume that the incoming buffer's bytes | ||
// won't get modified in-place later. | ||
// | ||
// To disable the shortcut above, hide the Bytes method by wrapping the buffer | ||
// with an io.Reader: | ||
// | ||
// Decode([...], struct{io.Reader}{buf}) | ||
func Decode(am ipld.NodeAssembler, r io.Reader) error { | ||
var data []byte | ||
if buf, ok := r.(interface{ Bytes() []byte }); ok { | ||
data = buf.Bytes() | ||
} else { | ||
var err error | ||
data, err = ioutil.ReadAll(r) | ||
if err != nil { | ||
return fmt.Errorf("could not decode raw node: %v", err) | ||
} | ||
} | ||
return am.AssignBytes(data) | ||
} | ||
|
||
// Encode implements encoding of a node with the raw codec. | ||
// | ||
// Note that Encode won't copy the node's bytes as returned by AsBytes, but the | ||
// call to Write will typically have to copy the bytes anyway. | ||
func Encode(node ipld.Node, w io.Writer) error { | ||
data, err := node.AsBytes() | ||
if err != nil { | ||
return err | ||
} | ||
_, err = w.Write(data) | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package raw | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"io" | ||
"testing" | ||
|
||
qt "github.com/frankban/quicktest" | ||
"github.com/ipfs/go-cid" | ||
ipld "github.com/ipld/go-ipld-prime" | ||
cidlink "github.com/ipld/go-ipld-prime/linking/cid" | ||
basicnode "github.com/ipld/go-ipld-prime/node/basic" | ||
) | ||
|
||
var tests = []struct { | ||
name string | ||
data []byte | ||
}{ | ||
{"Empty", nil}, | ||
{"Plaintext", []byte("hello there")}, | ||
{"JSON", []byte(`{"foo": "bar"}`)}, | ||
{"NullBytes", []byte("\x00\x00")}, | ||
} | ||
|
||
func TestRoundtrip(t *testing.T) { | ||
t.Parallel() | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
nb := basicnode.Prototype.Bytes.NewBuilder() | ||
r := bytes.NewBuffer(test.data) | ||
|
||
err := Decode(nb, r) | ||
qt.Assert(t, err, qt.IsNil) | ||
node := nb.Build() | ||
|
||
buf := new(bytes.Buffer) | ||
err = Encode(node, buf) | ||
qt.Assert(t, err, qt.IsNil) | ||
|
||
qt.Assert(t, buf.Bytes(), qt.DeepEquals, test.data) | ||
}) | ||
} | ||
} | ||
|
||
func TestRoundtripCidlink(t *testing.T) { | ||
t.Parallel() | ||
|
||
lb := cidlink.LinkBuilder{Prefix: cid.Prefix{ | ||
Version: 1, | ||
Codec: rawMulticodec, | ||
MhType: 0x17, | ||
MhLength: 4, | ||
}} | ||
node := basicnode.NewBytes([]byte("hello there")) | ||
|
||
buf := bytes.Buffer{} | ||
lnk, err := lb.Build(context.Background(), ipld.LinkContext{}, node, | ||
func(ipld.LinkContext) (io.Writer, ipld.StoreCommitter, error) { | ||
return &buf, func(lnk ipld.Link) error { return nil }, nil | ||
}, | ||
) | ||
qt.Assert(t, err, qt.IsNil) | ||
|
||
nb := basicnode.Prototype__Any{}.NewBuilder() | ||
err = lnk.Load(context.Background(), ipld.LinkContext{}, nb, | ||
func(lnk ipld.Link, _ ipld.LinkContext) (io.Reader, error) { | ||
return bytes.NewReader(buf.Bytes()), nil | ||
}, | ||
) | ||
qt.Assert(t, err, qt.IsNil) | ||
qt.Assert(t, nb.Build(), qt.DeepEquals, node) | ||
} | ||
|
||
// mustOnlyUseRead only exposes Read, hiding Bytes. | ||
type mustOnlyUseRead struct { | ||
buf *bytes.Buffer | ||
} | ||
|
||
func (r mustOnlyUseRead) Read(p []byte) (int, error) { | ||
return r.buf.Read(p) | ||
} | ||
|
||
// mustNotUseRead exposes Bytes and makes Read always error. | ||
type mustNotUseRead struct { | ||
buf *bytes.Buffer | ||
} | ||
|
||
func (r mustNotUseRead) Read(p []byte) (int, error) { | ||
return 0, fmt.Errorf("must not call Read") | ||
} | ||
|
||
func (r mustNotUseRead) Bytes() []byte { | ||
return r.buf.Bytes() | ||
} | ||
|
||
func TestDecodeBuffer(t *testing.T) { | ||
t.Parallel() | ||
|
||
var err error | ||
buf := bytes.NewBuffer([]byte("hello there")) | ||
|
||
err = Decode( | ||
basicnode.Prototype.Bytes.NewBuilder(), | ||
mustOnlyUseRead{buf}, | ||
) | ||
qt.Assert(t, err, qt.IsNil) | ||
|
||
err = Decode( | ||
basicnode.Prototype.Bytes.NewBuilder(), | ||
mustNotUseRead{buf}, | ||
) | ||
qt.Assert(t, err, qt.IsNil) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters