Skip to content

Commit

Permalink
Merge pull request #233 from fjl/rlpdump
Browse files Browse the repository at this point in the history
cmd/rlpdump: new helper command
  • Loading branch information
obscuren committed Jan 5, 2015
2 parents 952287d + b907a5d commit 2cfbf76
Showing 1 changed file with 128 additions and 0 deletions.
128 changes: 128 additions & 0 deletions cmd/rlpdump/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package main

import (
"bufio"
"bytes"
"encoding/hex"
"flag"
"fmt"
"io"
"os"
"strings"

"github.com/ethereum/go-ethereum/rlp"
)

var (
hexMode = flag.String("hex", "", "dump given hex data")
noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably")
)

func init() {
flag.Usage = func() {
fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "[-noascii] [-hex <data>] [filename]")
flag.PrintDefaults()
fmt.Fprintln(os.Stderr, `
Dumps RLP data from the given file in readable form.
If the filename is omitted, data is read from stdin.`)
}
}

func main() {
flag.Parse()

var r io.Reader
switch {
case *hexMode != "":
data, err := hex.DecodeString(*hexMode)
if err != nil {
die(err)
}
r = bytes.NewReader(data)

case flag.NArg() == 0:
r = os.Stdin

case flag.NArg() == 1:
fd, err := os.Open(flag.Arg(0))
if err != nil {
die(err)
}
defer fd.Close()
r = bufio.NewReader(fd)

default:
fmt.Fprintln(os.Stderr, "Error: too many arguments")
flag.Usage()
os.Exit(2)
}

s := rlp.NewStream(r)
for {
if err := dump(s, 0); err != nil {
if err != io.EOF {
die(err)
}
break
}
fmt.Println()
}
}

func dump(s *rlp.Stream, depth int) error {
kind, size, err := s.Kind()
if err != nil {
return err
}
switch kind {
case rlp.Byte, rlp.String:
str, err := s.Bytes()
if err != nil {
return err
}
if len(str) == 0 || !*noASCII && isASCII(str) {
fmt.Printf("%s%q", ws(depth), str)
} else {
fmt.Printf("%s%x", ws(depth), str)
}
case rlp.List:
s.List()
defer s.ListEnd()
if size == 0 {
fmt.Printf(ws(depth) + "[]")
return nil
} else {
fmt.Println(ws(depth) + "[")
for i := 0; ; i++ {
if i > 0 {
fmt.Print(",\n")
}
if err := dump(s, depth+1); err == rlp.EOL {
break
} else if err != nil {
return err
}
}
fmt.Print(ws(depth) + "]")
}
}
return nil
}

func isASCII(b []byte) bool {
for _, c := range b {
if c < 32 || c > 126 {
return false
}
}
return true
}

func ws(n int) string {
return strings.Repeat(" ", n)
}

func die(args ...interface{}) {
fmt.Fprintln(os.Stderr, args...)
os.Exit(1)
}

0 comments on commit 2cfbf76

Please sign in to comment.