154 lines
2.7 KiB
Go
154 lines
2.7 KiB
Go
package collections
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
type genesisHandler interface {
|
|
validateGenesis(r io.Reader) error
|
|
importGenesis(ctx context.Context, r io.Reader) error
|
|
exportGenesis(ctx context.Context, w io.Writer) error
|
|
defaultGenesis(w io.Writer) error
|
|
}
|
|
|
|
type jsonMapEntry struct {
|
|
Key json.RawMessage `json:"key"`
|
|
Value json.RawMessage `json:"value,omitempty"`
|
|
}
|
|
|
|
func (m Map[K, V]) validateGenesis(reader io.Reader) error {
|
|
return m.doDecodeJSON(reader, func(key K, value V) error {
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (m Map[K, V]) importGenesis(ctx context.Context, reader io.Reader) error {
|
|
return m.doDecodeJSON(reader, func(key K, value V) error {
|
|
return m.Set(ctx, key, value)
|
|
})
|
|
}
|
|
|
|
func (m Map[K, V]) exportGenesis(ctx context.Context, writer io.Writer) error {
|
|
_, err := io.WriteString(writer, "[")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
it, err := m.Iterate(ctx, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer it.Close()
|
|
|
|
first := true
|
|
for ; it.Valid(); it.Next() {
|
|
// add a comma before encoding the object
|
|
// for all objects besides the first one.
|
|
if !first {
|
|
_, err = io.WriteString(writer, ",")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
first = false
|
|
|
|
key, err := it.Key()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
keyBz, err := m.kc.EncodeJSON(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
value, err := it.Value()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
valueBz, err := m.vc.EncodeJSON(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
entry := jsonMapEntry{
|
|
Key: keyBz,
|
|
Value: valueBz,
|
|
}
|
|
|
|
bz, err := json.Marshal(entry)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = writer.Write(bz)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
_, err = io.WriteString(writer, "]")
|
|
return err
|
|
}
|
|
|
|
func (m Map[K, V]) doDecodeJSON(reader io.Reader, onEntry func(key K, value V) error) error {
|
|
decoder := json.NewDecoder(reader)
|
|
token, err := decoder.Token()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if token != json.Delim('[') {
|
|
return fmt.Errorf("expected [ got %s", token)
|
|
}
|
|
|
|
for decoder.More() {
|
|
var rawJSON json.RawMessage
|
|
err := decoder.Decode(&rawJSON)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var mapEntry jsonMapEntry
|
|
err = json.Unmarshal(rawJSON, &mapEntry)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
key, err := m.kc.DecodeJSON(mapEntry.Key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
value, err := m.vc.DecodeJSON(mapEntry.Value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = onEntry(key, value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
token, err = decoder.Token()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if token != json.Delim(']') {
|
|
return fmt.Errorf("expected ] got %s", token)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m Map[K, V]) defaultGenesis(writer io.Writer) error {
|
|
_, err := io.WriteString(writer, `[]`)
|
|
return err
|
|
}
|