multicodec.go 1.75 KB
Newer Older
Will Scott's avatar
Will Scott committed
1 2 3 4 5 6 7 8
package json

import (
	"fmt"
	"io"

	rfmtjson "github.com/polydawn/refmt/json"

tavit ohanian's avatar
tavit ohanian committed
9 10
	"gitlab.dms3.io/ld/go-ld-prime/codec/dagjson"
	"gitlab.dms3.io/ld/go-ld-prime/multicodec"
Will Scott's avatar
Will Scott committed
11 12 13
)

var (
tavit ohanian's avatar
tavit ohanian committed
14 15
	_ ld.Decoder = Decode
	_ ld.Encoder = Encode
Will Scott's avatar
Will Scott committed
16 17 18 19 20 21 22
)

func init() {
	multicodec.RegisterEncoder(0x0200, Encode)
	multicodec.RegisterDecoder(0x0200, Decode)
}

tavit ohanian's avatar
tavit ohanian committed
23
func Decode(na ld.NodeAssembler, r io.Reader) error {
Will Scott's avatar
Will Scott committed
24 25
	// Shell out directly to generic builder path.
	//  (There's not really any fastpaths of note for json.)
26 27 28 29
	err := dagjson.Unmarshal(na, rfmtjson.NewDecoder(r), dagjson.UnmarshalOptions{
		ParseLinks: false,
		ParseBytes: false,
	})
Will Scott's avatar
Will Scott committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
	if err != nil {
		return err
	}
	// Slurp any remaining whitespace.
	//  (This is relevant if our reader is tee'ing bytes to a hasher, and
	//   the json contained any trailing whitespace.)
	//  (We can't actually support multiple objects per reader from here;
	//   we can't unpeek if we find a non-whitespace token, so our only
	//    option is to error if this reader seems to contain more content.)
	var buf [1]byte
	for {
		_, err := r.Read(buf[:])
		switch buf[0] {
		case ' ', 0x0, '\t', '\r', '\n': // continue
		default:
			return fmt.Errorf("unexpected content after end of json object")
		}
		if err == nil {
			continue
		} else if err == io.EOF {
			return nil
		} else {
			return err
		}
	}
}

tavit ohanian's avatar
tavit ohanian committed
57
func Encode(n ld.Node, w io.Writer) error {
Will Scott's avatar
Will Scott committed
58 59 60 61 62 63
	// Shell out directly to generic inspection path.
	//  (There's not really any fastpaths of note for json.)
	// Write another function if you need to tune encoding options about whitespace.
	return dagjson.Marshal(n, rfmtjson.NewEncoder(w, rfmtjson.EncodeOptions{
		Line:   []byte{'\n'},
		Indent: []byte{'\t'},
64 65 66 67 68
	}), dagjson.MarshalOptions{
		EncodeLinks: false,
		EncodeBytes: false,
		SortMapKeys: false,
	})
Will Scott's avatar
Will Scott committed
69
}