1package main
2
3import (
4	"flag"
5	"fmt"
6	"io"
7	"os"
8	"path/filepath"
9
10	"github.com/linkedin/goavro/v2"
11)
12
13var (
14	showCount  = flag.Bool("count", false, "show count of data items")
15	showSchema = flag.Bool("schema", false, "show data schema")
16)
17
18func usage() {
19	executable, err := os.Executable()
20	if err != nil {
21		executable = os.Args[0]
22	}
23	base := filepath.Base(executable)
24	fmt.Fprintf(os.Stderr, "Usage of %s:\n", base)
25	fmt.Fprintf(os.Stderr, "\t%s [-count] [-schema] [file1.avro...]\n", base)
26	fmt.Fprintf(os.Stderr, "\tAs a special case, when there are no filename arguments, %s will read\n", base)
27	fmt.Fprintf(os.Stderr, "\tfrom its standard input.\n")
28	flag.PrintDefaults()
29	os.Exit(2)
30}
31
32func main() {
33	flag.Parse()
34
35	args := flag.Args()
36
37	if len(args) == 0 {
38		stat, err := os.Stdin.Stat()
39		if err != nil {
40			bail(err)
41		}
42		if (stat.Mode() & os.ModeCharDevice) != 0 {
43			usage()
44		}
45		if err := headerFromReader(os.Stdin, ""); err != nil {
46			bail(err)
47		}
48	}
49
50	for _, arg := range args {
51		fh, err := os.Open(arg)
52		if err != nil {
53			bail(err)
54		}
55		if len(args) > 1 {
56			arg += ": "
57		} else {
58			arg = ""
59		}
60		if err := headerFromReader(fh, arg); err != nil {
61			bail(err)
62		}
63		if err := fh.Close(); err != nil {
64			bail(err)
65		}
66	}
67}
68
69func headerFromReader(ior io.Reader, prefix string) error {
70	ocfr, err := goavro.NewOCFReader(ior)
71	if err != nil {
72		return err
73	}
74
75	fmt.Printf("%sCompression Algorithm (avro.codec): %q\n", prefix, ocfr.CompressionName())
76
77	if *showSchema {
78		fmt.Printf("%sSchema (avro.schema):\n%s\n", prefix, ocfr.Codec().Schema())
79	}
80
81	if !*showCount {
82		return nil
83	}
84
85	var decoded, errors int
86
87	for ocfr.Scan() {
88		_, err := ocfr.Read()
89		if err != nil {
90			fmt.Fprintf(os.Stderr, "%s\n", err)
91			errors++
92			continue
93		}
94		decoded++
95	}
96
97	if decoded > 0 {
98		fmt.Printf("%sSuccessfully decoded: %d\n", prefix, decoded)
99	}
100	if errors > 0 {
101		fmt.Printf("%sCannot decode: %d\n", prefix, errors)
102	}
103
104	return ocfr.Err()
105}
106
107func bail(err error) {
108	fmt.Fprintf(os.Stderr, "%s\n", err)
109	os.Exit(1)
110}
111