forked from mirror/go-ethereum
parent
b0854fbff5
commit
b907a5d765
@ -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) |
||||
} |
Loading…
Reference in new issue