File: main.go

package info (click to toggle)
golang-github-tinylib-msgp 1.4.0-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental, sid
  • size: 1,168 kB
  • sloc: makefile: 45
file content (152 lines) | stat: -rw-r--r-- 4,196 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// msgp is a code generation tool for
// creating methods to serialize and de-serialize
// Go data structures to and from MessagePack.
//
// This package is targeted at the `go generate` tool.
// To use it, include the following directive in a
// go source file with types requiring source generation:
//
//	//go:generate msgp
//
// The go generate tool should set the proper environment variables for
// the generator to execute without any command-line flags. However, the
// following options are supported, if you need them:
//
//	-o = output file name (default is {input}_gen.go)
//	-file = input file name (or directory; default is $GOFILE, which is set by the `go generate` command)
//	-io = satisfy the `msgp.Decodable` and `msgp.Encodable` interfaces (default is true)
//	-marshal = satisfy the `msgp.Marshaler` and `msgp.Unmarshaler` interfaces (default is true)
//	-tests = generate tests and benchmarks (default is true)
//
// For more information, please read README.md, and the wiki at github.com/tinylib/msgp
package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/tinylib/msgp/gen"
	"github.com/tinylib/msgp/parse"
	"github.com/tinylib/msgp/printer"
)

var (
	out        = flag.String("o", "", "output file")
	file       = flag.String("file", "", "input file")
	encode     = flag.Bool("io", true, "create Encode and Decode methods")
	marshal    = flag.Bool("marshal", true, "create Marshal and Unmarshal methods")
	tests      = flag.Bool("tests", true, "create tests and benchmarks")
	unexported = flag.Bool("unexported", false, "also process unexported types and fields")
	verbose    = flag.Bool("v", false, "verbose diagnostics")
	directives = stringArrFlags{}
)

func diagf(f string, args ...interface{}) {
	if !*verbose {
		return
	}
	if f[len(f)-1] != '\n' {
		f += "\n"
	}
	fmt.Fprintf(os.Stderr, f, args...)
}

func exitln(res string) {
	fmt.Fprintln(os.Stderr, res)
	os.Exit(1)
}

func main() {
	flag.Var(&directives, "d", "apply directive to all files. Multiple -d flags allowed. 'msgp:' can be omitted")
	flag.Parse()

	if *verbose {
		printer.Logf = diagf
		parse.Logf = diagf
	}
	for i, v := range directives {
		// Trim prefix and whitespace, if any.
		directives[i] = strings.TrimPrefix(strings.TrimSpace(v), "msgp:")
	}

	// GOFILE is set by go generate
	if *file == "" {
		*file = os.Getenv("GOFILE")
		if *file == "" {
			exitln("No file to parse.")
		}
	}

	var mode gen.Method
	if *encode {
		mode |= (gen.Encode | gen.Decode | gen.Size)
	}
	if *marshal {
		mode |= (gen.Marshal | gen.Unmarshal | gen.Size)
	}
	if *tests {
		mode |= gen.Test
	}

	if mode&^gen.Test == 0 {
		exitln("No methods to generate; -io=false && -marshal=false")
	}

	if err := Run(*file, mode, *unexported); err != nil {
		exitln(err.Error())
	}
}

// Run writes all methods using the associated file or path, e.g.
//
//	err := msgp.Run("path/to/myfile.go", gen.Size|gen.Marshal|gen.Unmarshal|gen.Test, false)
func Run(gofile string, mode gen.Method, unexported bool) error {
	if mode&^gen.Test == 0 {
		return nil
	}
	diagf("Input: \"%s\"\n", gofile)
	fs, err := parse.File(gofile, unexported, directives)
	if err != nil {
		return err
	}

	if len(fs.Identities) == 0 {
		diagf("No types requiring code generation were found!")
	}

	return printer.PrintFile(newFilename(gofile, fs.Package), fs, mode)
}

// picks a new file name based on input flags and input filename(s).
func newFilename(old string, pkg string) string {
	if *out != "" {
		if pre := strings.TrimPrefix(*out, old); len(pre) > 0 &&
			!strings.HasSuffix(*out, ".go") {
			return filepath.Join(old, *out)
		}
		return *out
	}

	if fi, err := os.Stat(old); err == nil && fi.IsDir() {
		old = filepath.Join(old, pkg)
	}
	// new file name is old file name + _gen.go
	return strings.TrimSuffix(old, ".go") + "_gen.go"
}

// stringArrFlags is a flag.Value that accepts multiple values
type stringArrFlags []string

// String is an implementation of the flag.Value interface
func (i *stringArrFlags) String() string {
	return fmt.Sprintf("%v", *i)
}

// Set is an implementation of the flag.Value interface
func (i *stringArrFlags) Set(value string) error {
	*i = append(*i, value)
	return nil
}