corso/src/cmd/jsondebug/decoder/jsonparser_decode.go
Ashlie Martinez 1cc3247721 Interface/code for running benchmarks on buffers
Setup things so we can remove the time it takes to read the input data.
2023-03-31 16:50:09 -07:00

135 lines
2.7 KiB
Go

package decoder
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"time"
"github.com/buger/jsonparser"
"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
"github.com/alcionai/corso/src/cmd/jsondebug/common"
)
var _ common.ManifestDecoder = JsonParser{}
//revive:disable-next-line:var-naming
type JsonParser struct{}
func (d JsonParser) Decode(r io.Reader, gcStats bool) error {
if gcStats {
common.PrintMemUsage()
}
data, err := ioutil.ReadAll(r)
if err != nil {
return errors.Wrap(err, "reading data")
}
return parseManifestData(data, gcStats)
}
func (d JsonParser) DecodeBytes(data []byte, gcStats bool) error {
if gcStats {
common.PrintMemUsage()
}
return parseManifestData(data, gcStats)
}
func parseManifestData(data []byte, gcStats bool) error {
if gcStats {
common.PrintMemUsage()
}
var (
errs *multierror.Error
output = common.Manifest{
Entries: []*common.ManifestEntry{},
}
)
_ = output
// var handler func([]byte, []byte, jsonparser.ValueType, int) error
// handler := func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error {
// fmt.Printf("Key: '%s'\n Value: '%s'\n Type: %s\n", string(key), string(value), dataType)
// return nil
// }
//nolint:errcheck
jsonparser.ArrayEach(data, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
e, errInner := getManifestEntry(value)
if errInner != nil {
errs = multierror.Append(errs, err)
}
output.Entries = append(output.Entries, e)
}, "entries")
if gcStats {
common.PrintMemUsage()
fmt.Printf("Decoded %d entries\n", len(output.Entries))
}
return errs.ErrorOrNil()
}
func getManifestEntry(data []byte) (*common.ManifestEntry, error) {
var (
errs *multierror.Error
err error
e = &common.ManifestEntry{}
paths = [][]string{
{"id"},
{"labels"},
{"modified"},
{"deleted"},
{"data"},
}
)
jsonparser.EachKey(data, func(idx int, value []byte, vt jsonparser.ValueType, iterErr error) {
switch idx {
case 0:
e.ID = string(value)
case 1:
err = json.Unmarshal(value, &e.Labels)
if err != nil {
err = errors.Wrap(err, "unmarshalling labels")
}
case 2:
e.ModTime, err = time.Parse(time.RFC3339, string(value))
if err != nil {
err = errors.Wrap(err, "unmarshalling modtime")
}
case 3:
err = json.Unmarshal(value, &e.Deleted)
if err != nil {
err = errors.Wrap(err, "unmarshalling deleted")
}
case 4:
e.Content = make([]byte, len(value))
n := copy(e.Content, value)
if n != len(value) {
err = errors.Errorf("failed to copy content; got %d bytes", n)
}
default:
err = errors.Errorf("unexpected input %v", idx)
}
errs = multierror.Append(errs, err)
}, paths...)
return e, errs.ErrorOrNil()
}