135 lines
2.7 KiB
Go
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()
|
|
}
|