@@ -25,7 +25,9 @@ import (
25
25
"flag"
26
26
"fmt"
27
27
"io"
28
+ "math"
28
29
"os"
30
+ "strconv"
29
31
"strings"
30
32
31
33
"github.com/ethereum/go-ethereum/common"
37
39
reverseMode = flag .Bool ("reverse" , false , "convert ASCII to rlp" )
38
40
noASCII = flag .Bool ("noascii" , false , "don't print ASCII strings readably" )
39
41
single = flag .Bool ("single" , false , "print only the first element, discard the rest" )
42
+ showpos = flag .Bool ("pos" , false , "display element byte posititions" )
40
43
)
41
44
42
45
func init () {
@@ -52,31 +55,37 @@ If the filename is omitted, data is read from stdin.`)
52
55
func main () {
53
56
flag .Parse ()
54
57
55
- var r io. Reader
58
+ var r * inStream
56
59
switch {
57
60
case * hexMode != "" :
58
61
data , err := hex .DecodeString (strings .TrimPrefix (* hexMode , "0x" ))
59
62
if err != nil {
60
63
die (err )
61
64
}
62
- r = bytes .NewReader (data )
65
+ r = newInStream ( bytes .NewReader (data ), int64 ( len ( data )) )
63
66
64
67
case flag .NArg () == 0 :
65
- r = os .Stdin
68
+ r = newInStream ( bufio . NewReader ( os .Stdin ), 0 )
66
69
67
70
case flag .NArg () == 1 :
68
71
fd , err := os .Open (flag .Arg (0 ))
69
72
if err != nil {
70
73
die (err )
71
74
}
72
75
defer fd .Close ()
73
- r = fd
76
+ var size int64
77
+ finfo , err := fd .Stat ()
78
+ if err == nil {
79
+ size = finfo .Size ()
80
+ }
81
+ r = newInStream (bufio .NewReader (fd ), size )
74
82
75
83
default :
76
84
fmt .Fprintln (os .Stderr , "Error: too many arguments" )
77
85
flag .Usage ()
78
86
os .Exit (2 )
79
87
}
88
+
80
89
out := os .Stdout
81
90
if * reverseMode {
82
91
data , err := textToRlp (r )
@@ -93,10 +102,10 @@ func main() {
93
102
}
94
103
}
95
104
96
- func rlpToText (r io. Reader , out io.Writer ) error {
97
- s := rlp .NewStream (r , 0 )
105
+ func rlpToText (in * inStream , out io.Writer ) error {
106
+ stream := rlp .NewStream (in , 0 )
98
107
for {
99
- if err := dump (s , 0 , out ); err != nil {
108
+ if err := dump (in , stream , 0 , out ); err != nil {
100
109
if err != io .EOF {
101
110
return err
102
111
}
@@ -110,7 +119,10 @@ func rlpToText(r io.Reader, out io.Writer) error {
110
119
return nil
111
120
}
112
121
113
- func dump (s * rlp.Stream , depth int , out io.Writer ) error {
122
+ func dump (in * inStream , s * rlp.Stream , depth int , out io.Writer ) error {
123
+ if * showpos {
124
+ fmt .Fprintf (out , "%s: " , in .posLabel ())
125
+ }
114
126
kind , size , err := s .Kind ()
115
127
if err != nil {
116
128
return err
@@ -137,7 +149,7 @@ func dump(s *rlp.Stream, depth int, out io.Writer) error {
137
149
if i > 0 {
138
150
fmt .Fprint (out , ",\n " )
139
151
}
140
- if err := dump (s , depth + 1 , out ); err == rlp .EOL {
152
+ if err := dump (in , s , depth + 1 , out ); err == rlp .EOL {
141
153
break
142
154
} else if err != nil {
143
155
return err
@@ -208,3 +220,36 @@ func textToRlp(r io.Reader) ([]byte, error) {
208
220
data , err := rlp .EncodeToBytes (obj [0 ])
209
221
return data , err
210
222
}
223
+
224
+ type inStream struct {
225
+ br rlp.ByteReader
226
+ pos int
227
+ columns int
228
+ }
229
+
230
+ func newInStream (br rlp.ByteReader , totalSize int64 ) * inStream {
231
+ col := int (math .Ceil (math .Log10 (float64 (totalSize ))))
232
+ return & inStream {br : br , columns : col }
233
+ }
234
+
235
+ func (rc * inStream ) Read (b []byte ) (n int , err error ) {
236
+ n , err = rc .br .Read (b )
237
+ rc .pos += n
238
+ return n , err
239
+ }
240
+
241
+ func (rc * inStream ) ReadByte () (byte , error ) {
242
+ b , err := rc .br .ReadByte ()
243
+ if err == nil {
244
+ rc .pos ++
245
+ }
246
+ return b , err
247
+ }
248
+
249
+ func (rc * inStream ) posLabel () string {
250
+ l := strconv .FormatInt (int64 (rc .pos ), 10 )
251
+ if len (l ) < rc .columns {
252
+ l = strings .Repeat (" " , rc .columns - len (l )) + l
253
+ }
254
+ return l
255
+ }
0 commit comments