cmd/rlpdump: add -pos flag, displaying byte positions (#28785)

This commit is contained in:
Felix Lange 2024-01-14 12:32:48 +01:00 committed by GitHub
parent 29b73555ae
commit 1485814f89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 10 deletions

@ -25,7 +25,9 @@ import (
"flag" "flag"
"fmt" "fmt"
"io" "io"
"math"
"os" "os"
"strconv"
"strings" "strings"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -37,6 +39,7 @@ var (
reverseMode = flag.Bool("reverse", false, "convert ASCII to rlp") reverseMode = flag.Bool("reverse", false, "convert ASCII to rlp")
noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably") noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably")
single = flag.Bool("single", false, "print only the first element, discard the rest") single = flag.Bool("single", false, "print only the first element, discard the rest")
showpos = flag.Bool("pos", false, "display element byte posititions")
) )
func init() { func init() {
@ -52,17 +55,17 @@ If the filename is omitted, data is read from stdin.`)
func main() { func main() {
flag.Parse() flag.Parse()
var r io.Reader var r *inStream
switch { switch {
case *hexMode != "": case *hexMode != "":
data, err := hex.DecodeString(strings.TrimPrefix(*hexMode, "0x")) data, err := hex.DecodeString(strings.TrimPrefix(*hexMode, "0x"))
if err != nil { if err != nil {
die(err) die(err)
} }
r = bytes.NewReader(data) r = newInStream(bytes.NewReader(data), int64(len(data)))
case flag.NArg() == 0: case flag.NArg() == 0:
r = os.Stdin r = newInStream(bufio.NewReader(os.Stdin), 0)
case flag.NArg() == 1: case flag.NArg() == 1:
fd, err := os.Open(flag.Arg(0)) fd, err := os.Open(flag.Arg(0))
@ -70,13 +73,19 @@ func main() {
die(err) die(err)
} }
defer fd.Close() defer fd.Close()
r = fd var size int64
finfo, err := fd.Stat()
if err == nil {
size = finfo.Size()
}
r = newInStream(bufio.NewReader(fd), size)
default: default:
fmt.Fprintln(os.Stderr, "Error: too many arguments") fmt.Fprintln(os.Stderr, "Error: too many arguments")
flag.Usage() flag.Usage()
os.Exit(2) os.Exit(2)
} }
out := os.Stdout out := os.Stdout
if *reverseMode { if *reverseMode {
data, err := textToRlp(r) data, err := textToRlp(r)
@ -93,10 +102,10 @@ func main() {
} }
} }
func rlpToText(r io.Reader, out io.Writer) error { func rlpToText(in *inStream, out io.Writer) error {
s := rlp.NewStream(r, 0) stream := rlp.NewStream(in, 0)
for { for {
if err := dump(s, 0, out); err != nil { if err := dump(in, stream, 0, out); err != nil {
if err != io.EOF { if err != io.EOF {
return err return err
} }
@ -110,7 +119,10 @@ func rlpToText(r io.Reader, out io.Writer) error {
return nil return nil
} }
func dump(s *rlp.Stream, depth int, out io.Writer) error { func dump(in *inStream, s *rlp.Stream, depth int, out io.Writer) error {
if *showpos {
fmt.Fprintf(out, "%s: ", in.posLabel())
}
kind, size, err := s.Kind() kind, size, err := s.Kind()
if err != nil { if err != nil {
return err return err
@ -137,7 +149,7 @@ func dump(s *rlp.Stream, depth int, out io.Writer) error {
if i > 0 { if i > 0 {
fmt.Fprint(out, ",\n") fmt.Fprint(out, ",\n")
} }
if err := dump(s, depth+1, out); err == rlp.EOL { if err := dump(in, s, depth+1, out); err == rlp.EOL {
break break
} else if err != nil { } else if err != nil {
return err return err
@ -208,3 +220,36 @@ func textToRlp(r io.Reader) ([]byte, error) {
data, err := rlp.EncodeToBytes(obj[0]) data, err := rlp.EncodeToBytes(obj[0])
return data, err return data, err
} }
type inStream struct {
br rlp.ByteReader
pos int
columns int
}
func newInStream(br rlp.ByteReader, totalSize int64) *inStream {
col := int(math.Ceil(math.Log10(float64(totalSize))))
return &inStream{br: br, columns: col}
}
func (rc *inStream) Read(b []byte) (n int, err error) {
n, err = rc.br.Read(b)
rc.pos += n
return n, err
}
func (rc *inStream) ReadByte() (byte, error) {
b, err := rc.br.ReadByte()
if err == nil {
rc.pos++
}
return b, err
}
func (rc *inStream) posLabel() string {
l := strconv.FormatInt(int64(rc.pos), 10)
if len(l) < rc.columns {
l = strings.Repeat(" ", rc.columns-len(l)) + l
}
return l
}

@ -34,7 +34,8 @@ func TestRoundtrip(t *testing.T) {
"0xc780c0c1c0825208", "0xc780c0c1c0825208",
} { } {
var out strings.Builder var out strings.Builder
err := rlpToText(bytes.NewReader(common.FromHex(want)), &out) in := newInStream(bytes.NewReader(common.FromHex(want)), 0)
err := rlpToText(in, &out)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }