github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/rlpdump/main.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:31</date> 10 //</624342604854595584> 11 12 13 // 14 package main 15 16 import ( 17 "bytes" 18 "encoding/hex" 19 "flag" 20 "fmt" 21 "io" 22 "os" 23 "strings" 24 25 "github.com/ethereum/go-ethereum/rlp" 26 ) 27 28 var ( 29 hexMode = flag.String("hex", "", "dump given hex data") 30 noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably") 31 single = flag.Bool("single", false, "print only the first element, discard the rest") 32 ) 33 34 func init() { 35 flag.Usage = func() { 36 fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "[-noascii] [-hex <data>] [filename]") 37 flag.PrintDefaults() 38 fmt.Fprintln(os.Stderr, ` 39 Dumps RLP data from the given file in readable form. 40 If the filename is omitted, data is read from stdin.`) 41 } 42 } 43 44 func main() { 45 flag.Parse() 46 47 var r io.Reader 48 switch { 49 case *hexMode != "": 50 data, err := hex.DecodeString(strings.TrimPrefix(*hexMode, "0x")) 51 if err != nil { 52 die(err) 53 } 54 r = bytes.NewReader(data) 55 56 case flag.NArg() == 0: 57 r = os.Stdin 58 59 case flag.NArg() == 1: 60 fd, err := os.Open(flag.Arg(0)) 61 if err != nil { 62 die(err) 63 } 64 defer fd.Close() 65 r = fd 66 67 default: 68 fmt.Fprintln(os.Stderr, "Error: too many arguments") 69 flag.Usage() 70 os.Exit(2) 71 } 72 73 s := rlp.NewStream(r, 0) 74 for { 75 if err := dump(s, 0); err != nil { 76 if err != io.EOF { 77 die(err) 78 } 79 break 80 } 81 fmt.Println() 82 if *single { 83 break 84 } 85 } 86 } 87 88 func dump(s *rlp.Stream, depth int) error { 89 kind, size, err := s.Kind() 90 if err != nil { 91 return err 92 } 93 switch kind { 94 case rlp.Byte, rlp.String: 95 str, err := s.Bytes() 96 if err != nil { 97 return err 98 } 99 if len(str) == 0 || !*noASCII && isASCII(str) { 100 fmt.Printf("%s%q", ws(depth), str) 101 } else { 102 fmt.Printf("%s%x", ws(depth), str) 103 } 104 case rlp.List: 105 s.List() 106 defer s.ListEnd() 107 if size == 0 { 108 fmt.Print(ws(depth) + "[]") 109 } else { 110 fmt.Println(ws(depth) + "[") 111 for i := 0; ; i++ { 112 if i > 0 { 113 fmt.Print(",\n") 114 } 115 if err := dump(s, depth+1); err == rlp.EOL { 116 break 117 } else if err != nil { 118 return err 119 } 120 } 121 fmt.Print(ws(depth) + "]") 122 } 123 } 124 return nil 125 } 126 127 func isASCII(b []byte) bool { 128 for _, c := range b { 129 if c < 32 || c > 126 { 130 return false 131 } 132 } 133 return true 134 } 135 136 func ws(n int) string { 137 return strings.Repeat(" ", n) 138 } 139 140 func die(args ...interface{}) { 141 fmt.Fprintln(os.Stderr, args...) 142 os.Exit(1) 143 } 144