github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/cmd/rlpdump/main.go (about)

     1  //  Copyright 2018 The go-ethereum Authors
     2  //  Copyright 2019 The go-aigar Authors
     3  //  This file is part of the go-aigar library.
     4  //
     5  //  The go-aigar library is free software: you can redistribute it and/or modify
     6  //  it under the terms of the GNU Lesser General Public License as published by
     7  //  the Free Software Foundation, either version 3 of the License, or
     8  //  (at your option) any later version.
     9  //
    10  //  The go-aigar library is distributed in the hope that it will be useful,
    11  //  but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  //  GNU Lesser General Public License for more details.
    14  //
    15  //  You should have received a copy of the GNU Lesser General Public License
    16  //  along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  // rlpdump is a pretty-printer for RLP data.
    19  package main
    20  
    21  import (
    22  	"bytes"
    23  	"encoding/hex"
    24  	"flag"
    25  	"fmt"
    26  	"io"
    27  	"os"
    28  	"strings"
    29  
    30  	"github.com/AigarNetwork/aigar/rlp"
    31  )
    32  
    33  var (
    34  	hexMode = flag.String("hex", "", "dump given hex data")
    35  	noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably")
    36  	single  = flag.Bool("single", false, "print only the first element, discard the rest")
    37  )
    38  
    39  func init() {
    40  	flag.Usage = func() {
    41  		fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "[-noascii] [-hex <data>] [filename]")
    42  		flag.PrintDefaults()
    43  		fmt.Fprintln(os.Stderr, `
    44  Dumps RLP data from the given file in readable form.
    45  If the filename is omitted, data is read from stdin.`)
    46  	}
    47  }
    48  
    49  func main() {
    50  	flag.Parse()
    51  
    52  	var r io.Reader
    53  	switch {
    54  	case *hexMode != "":
    55  		data, err := hex.DecodeString(strings.TrimPrefix(*hexMode, "0x"))
    56  		if err != nil {
    57  			die(err)
    58  		}
    59  		r = bytes.NewReader(data)
    60  
    61  	case flag.NArg() == 0:
    62  		r = os.Stdin
    63  
    64  	case flag.NArg() == 1:
    65  		fd, err := os.Open(flag.Arg(0))
    66  		if err != nil {
    67  			die(err)
    68  		}
    69  		defer fd.Close()
    70  		r = fd
    71  
    72  	default:
    73  		fmt.Fprintln(os.Stderr, "Error: too many arguments")
    74  		flag.Usage()
    75  		os.Exit(2)
    76  	}
    77  
    78  	s := rlp.NewStream(r, 0)
    79  	for {
    80  		if err := dump(s, 0); err != nil {
    81  			if err != io.EOF {
    82  				die(err)
    83  			}
    84  			break
    85  		}
    86  		fmt.Println()
    87  		if *single {
    88  			break
    89  		}
    90  	}
    91  }
    92  
    93  func dump(s *rlp.Stream, depth int) error {
    94  	kind, size, err := s.Kind()
    95  	if err != nil {
    96  		return err
    97  	}
    98  	switch kind {
    99  	case rlp.Byte, rlp.String:
   100  		str, err := s.Bytes()
   101  		if err != nil {
   102  			return err
   103  		}
   104  		if len(str) == 0 || !*noASCII && isASCII(str) {
   105  			fmt.Printf("%s%q", ws(depth), str)
   106  		} else {
   107  			fmt.Printf("%s%x", ws(depth), str)
   108  		}
   109  	case rlp.List:
   110  		s.List()
   111  		defer s.ListEnd()
   112  		if size == 0 {
   113  			fmt.Print(ws(depth) + "[]")
   114  		} else {
   115  			fmt.Println(ws(depth) + "[")
   116  			for i := 0; ; i++ {
   117  				if i > 0 {
   118  					fmt.Print(",\n")
   119  				}
   120  				if err := dump(s, depth+1); err == rlp.EOL {
   121  					break
   122  				} else if err != nil {
   123  					return err
   124  				}
   125  			}
   126  			fmt.Print(ws(depth) + "]")
   127  		}
   128  	}
   129  	return nil
   130  }
   131  
   132  func isASCII(b []byte) bool {
   133  	for _, c := range b {
   134  		if c < 32 || c > 126 {
   135  			return false
   136  		}
   137  	}
   138  	return true
   139  }
   140  
   141  func ws(n int) string {
   142  	return strings.Repeat("  ", n)
   143  }
   144  
   145  func die(args ...interface{}) {
   146  	fmt.Fprintln(os.Stderr, args...)
   147  	os.Exit(1)
   148  }