Skip to content

Commit

Permalink
fix(cmd): Use JSON for pretty-printing events/results
Browse files Browse the repository at this point in the history
YAML uses a very verbose notation for printing byte arrays which are
quite common in our data structures. Until we have proper pretty
printing implementations for event/result structures, JSON produces
nicer output.
  • Loading branch information
kostko committed May 12, 2023
1 parent df1f4d1 commit 27c46a5
Showing 1 changed file with 67 additions and 14 deletions.
81 changes: 67 additions & 14 deletions cmd/inspect/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package inspect
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"

ethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"

"github.com/oasisprotocol/oasis-core/go/common/cbor"
"github.com/oasisprotocol/oasis-core/go/common/crypto/hash"
Expand Down Expand Up @@ -194,11 +194,11 @@ var blockCmd = &cobra.Command{
case res.Ok != nil:
fmt.Printf("Status: ok\n")
fmt.Printf("Data:\n")
prettyPrintCBOR(" ", res.Ok)
prettyPrintCBOR(" ", "result", res.Ok)
case res.Unknown != nil:
fmt.Printf("Status: unknown\n")
fmt.Printf("Data:\n")
prettyPrintCBOR(" ", res.Unknown)
prettyPrintCBOR(" ", "result", res.Unknown)
default:
fmt.Printf("[unsupported result kind]\n")
}
Expand All @@ -222,27 +222,80 @@ var blockCmd = &cobra.Command{
},
}

func prettyPrintCBOR(indent string, data []byte) {
func prettyPrintCBOR(indent string, kind string, data []byte) {
var body interface{}
if err := cbor.Unmarshal(data, &body); err != nil {
fmt.Printf("%s%s\n", indent, base64.StdEncoding.EncodeToString(data))
rawPrintData(indent, kind, data)
return
}

prettyPrintStruct(indent, data, body)
prettyPrintStruct(indent, kind, data, body)
}

func prettyPrintStruct(indent string, data []byte, body interface{}) {
func encode(in interface{}) (interface{}, error) {
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}

switch v.Kind() {
case reflect.Slice:
// Walk slices.
for i := 0; i < v.Len(); i++ {
elem := v.Index(i)
encoded, err := encode(elem.Interface())
if err != nil {
return nil, err
}
elem.Set(reflect.ValueOf(encoded))
}
return v.Interface(), nil
case reflect.Map:
// Convert maps to map[string]interface{}.
result := make(map[string]interface{})
iter := v.MapRange()
for iter.Next() {
k := iter.Key()
val := iter.Value()

kStr, ok := k.Interface().(string)
if !ok {
return nil, fmt.Errorf("can only convert maps with string keys")
}

value, err := encode(val.Interface())
if err != nil {
return nil, err
}
result[kStr] = value
}
return result, nil
default:
// Pass everything else unchanged.
return v.Interface(), nil
}
}

func rawPrintData(indent string, kind string, data []byte) {
fmt.Printf("%s[showing raw %s data]\n", indent, kind)
fmt.Printf("%s%s\n", indent, base64.StdEncoding.EncodeToString(data))
}

func prettyPrintStruct(indent string, kind string, data []byte, body interface{}) {
// TODO: Support the pretty printer.
pretty, err := yaml.Marshal(body)
body, err := encode(body)
if err != nil {
rawPrintData(indent, kind, data)
return
}

pretty, err := json.MarshalIndent(body, indent, " ")
if err != nil {
fmt.Printf("%s%s\n", indent, base64.StdEncoding.EncodeToString(data))
rawPrintData(indent, kind, data)
return
}

output := string(pretty)
output = strings.ReplaceAll(output, "\n", "\n"+indent)
output = strings.TrimSpace(output)
fmt.Println(indent + output)
}

Expand All @@ -258,10 +311,10 @@ func prettyPrintEvent(indent string, evIndex int, ev *types.Event, decoders []cl
continue
}
if decoded != nil {
prettyPrintStruct(indent+" ", ev.Value, decoded)
prettyPrintStruct(indent+" ", "event", ev.Value, decoded)
return
}
}

prettyPrintCBOR(indent+" ", ev.Value)
prettyPrintCBOR(indent+" ", "event", ev.Value)
}

0 comments on commit 27c46a5

Please sign in to comment.