codec.go 1.93 KB
Newer Older
1
// Package raw implements LD's raw codec, which simply writes and reads a Node
2 3 4 5
// 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
tavit ohanian's avatar
tavit ohanian committed
6
// such as gitlab.dms3.io/ld/go-ld-prime/node/basic.Prototype.Bytes.
7 8 9 10 11 12 13
package raw

import (
	"fmt"
	"io"
	"io/ioutil"

tavit ohanian's avatar
tavit ohanian committed
14
	ld "gitlab.dms3.io/ld/go-ld-prime"
tavit ohanian's avatar
tavit ohanian committed
15
	"gitlab.dms3.io/ld/go-ld-prime/multicodec"
16 17
)

tavit ohanian's avatar
tavit ohanian committed
18
// TODO(mvdan): make go-ld-prime use go-multicodec soon
19 20
const rawMulticodec = 0x55

21
var (
tavit ohanian's avatar
tavit ohanian committed
22 23
	_ ld.Decoder = Decode
	_ ld.Encoder = Encode
24 25
)

26
func init() {
27 28
	multicodec.RegisterEncoder(rawMulticodec, Encode)
	multicodec.RegisterDecoder(rawMulticodec, Decode)
29 30 31 32 33 34 35 36 37 38 39 40 41 42
}

// 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})
tavit ohanian's avatar
tavit ohanian committed
43
func Decode(am ld.NodeAssembler, r io.Reader) error {
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
	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.
tavit ohanian's avatar
tavit ohanian committed
61
func Encode(node ld.Node, w io.Writer) error {
62 63 64 65 66 67 68
	data, err := node.AsBytes()
	if err != nil {
		return err
	}
	_, err = w.Write(data)
	return err
}