cosmos-sdk/collections/genesis.go
testinginprod b61c72fc66
feat(collections): do not error when iterating empty collections (#17290)
Co-authored-by: unknown unknown <unknown@unknown>
2023-08-07 13:53:02 +00:00

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
}