aboutsummaryrefslogtreecommitdiff
path: root/cmd/r2-pdata2json
diff options
context:
space:
mode:
authorpg9182 <96569817+pg9182@users.noreply.github.com>2022-10-12 21:51:50 -0400
committerpg9182 <96569817+pg9182@users.noreply.github.com>2022-10-12 21:51:50 -0400
commit26f00fb2c53ad001ff82a5a6f711ba6dbb0649ad (patch)
tree80c7b2aa7427642340ac15410aa4fcc46ad49559 /cmd/r2-pdata2json
parentaaa46de4d284ba0038ea8f4177f39b171b80ac48 (diff)
downloadAtlas-26f00fb2c53ad001ff82a5a6f711ba6dbb0649ad.tar.gz
Atlas-26f00fb2c53ad001ff82a5a6f711ba6dbb0649ad.zip
cmd/r2-pdata2json: Implement command to convert pdata to JSON
Also supports filtering properties.
Diffstat (limited to 'cmd/r2-pdata2json')
-rw-r--r--cmd/r2-pdata2json/main.go107
1 files changed, 107 insertions, 0 deletions
diff --git a/cmd/r2-pdata2json/main.go b/cmd/r2-pdata2json/main.go
new file mode 100644
index 0000000..19473b9
--- /dev/null
+++ b/cmd/r2-pdata2json/main.go
@@ -0,0 +1,107 @@
+// Command r2-pdata2json converts pdata to JSON.
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/pg9182/atlas/pkg/pdata"
+ "github.com/spf13/pflag"
+)
+
+var opt struct {
+ Compact bool
+ Invert bool
+ Filter []string
+ Help bool
+}
+
+func init() {
+ pflag.BoolVarP(&opt.Compact, "compact", "c", false, "Don't format json")
+ pflag.BoolVarP(&opt.Invert, "invert", "v", false, "Use filter to include instead of exclude")
+ pflag.StringSliceVarP(&opt.Filter, "filter", "e", nil, "Exclude pdef fields (use . to select nested fields)")
+ pflag.BoolVarP(&opt.Help, "help", "h", false, "Show this help text")
+}
+
+func main() {
+ pflag.Parse()
+
+ if pflag.NArg() > 1 || opt.Help {
+ fmt.Printf("usage: %s [options] [file|-]\n\noptions:\n%s\npdef version: %d\n", os.Args[0], pflag.CommandLine.FlagUsages(), pdata.Version)
+ if opt.Help {
+ os.Exit(2)
+ }
+ os.Exit(0)
+ }
+
+ var err error
+ var buf []byte
+ if pflag.NArg() == 1 && pflag.Arg(0) != "-" {
+ buf, err = os.ReadFile(pflag.Arg(0))
+ } else {
+ buf, err = io.ReadAll(os.Stdin)
+ }
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error: read pdata: %v\n", err)
+ os.Exit(1)
+ }
+
+ var pd pdata.Pdata
+ if err := pd.UnmarshalBinary(buf); err != nil {
+ fmt.Fprintf(os.Stderr, "error: parse pdata: %v\n", err)
+ os.Exit(1)
+ }
+
+ jbuf, err := pd.MarshalJSONFilter(mkfilter(opt.Invert, opt.Filter...))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error: encode json: %v\n", err)
+ os.Exit(1)
+ }
+
+ var fbuf []byte
+ if opt.Compact {
+ fbuf, err = json.Marshal(json.RawMessage(jbuf))
+ } else {
+ fbuf, err = json.MarshalIndent(json.RawMessage(jbuf), "", " ")
+ }
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error: format json: %v\n", err)
+ os.Exit(1)
+ }
+
+ fmt.Fprintln(os.Stdout, string(fbuf))
+}
+
+func mkfilter(invert bool, filter ...string) func(path ...string) bool {
+ if len(filter) == 0 {
+ return nil
+ }
+ // this is completely unoptimized (n^m^o), but this tool is just for testing, so whatever
+ return func(path ...string) bool {
+ if !invert {
+ pj := strings.Join(path, ".") + "."
+ for _, f := range filter {
+ f += "."
+ if strings.HasPrefix(pj, f) {
+ return false // filter is an exact march for the path
+ }
+ }
+ return true
+ }
+
+ pj := strings.Join(path, ".") + "."
+ for _, f := range filter {
+ f += "."
+ if strings.HasPrefix(pj, f) {
+ return true // filter is an exact match for the path
+ }
+ if strings.HasPrefix(f, pj) {
+ return true // a parent of the filter is an exact match for the path
+ }
+ }
+ return false
+ }
+}