~bigbes/tarantool

tarantool-protobuf

ref: 2ed0f4b5b17a1235cbcef16005370d430b2b5424 tarantool-protobuf/cmd/protoc-gen-tarantool/main.go -rw-r--r-- 2.5 KiB
2ed0f4b5 — Eugene Blikh wire: validate field number and minimal encoding in decode_tag 3 months ago
                                                                                
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
// protoc-gen-tarantool is a protoc plugin that generates Lua code targeting
// Tarantool's LuaJIT runtime, paired with the runtime/protobuf Lua package.
//
// Usage:
//   protoc --tarantool_out=./out --plugin=./protoc-gen-tarantool foo.proto
//
// File option (in your .proto):
//   import "tarantool/tarantool.proto";
//   option (tarantool.lua_package) = "myapp.proto.foo";
package main

import (
	"flag"
	"fmt"
	"io"
	"os"
	"strings"

	"google.golang.org/protobuf/compiler/protogen"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/descriptorpb"
	"google.golang.org/protobuf/types/pluginpb"

	"sourcecraft.dev/bigbes/tarantool-protobuf/cmd/protoc-gen-tarantool/internal/gen"
)

func main() {
	in, err := io.ReadAll(os.Stdin)
	if err != nil {
		fail("read stdin: %v", err)
	}
	req := &pluginpb.CodeGeneratorRequest{}
	if err := proto.Unmarshal(in, req); err != nil {
		fail("parse CodeGeneratorRequest: %v", err)
	}

	// protogen requires a go_package on every input file even when we are not
	// generating Go. Inject a synthetic value when it's missing — it's never
	// surfaced to the generated Lua.
	for _, f := range req.ProtoFile {
		if f.Options == nil {
			f.Options = &descriptorpb.FileOptions{}
		}
		if f.Options.GoPackage == nil {
			stub := "tarantoolpb_synthetic/" + strings.TrimSuffix(f.GetName(), ".proto")
			f.Options.GoPackage = proto.String(stub)
		}
	}

	var flags flag.FlagSet
	modeFlag := flags.String("mode", "full", "codegen mode: full | runtime")
	prefixFlag := flags.String("prefix", "",
		"prefix prepended to every generated module's Lua require path "+
			"(useful for side-by-side generation in tests)")
	plugin, err := protogen.Options{ParamFunc: flags.Set}.New(req)
	if err != nil {
		fail("init protogen: %v", err)
	}

	mode, err := gen.ParseMode(*modeFlag)
	if err != nil {
		fail("%v", err)
	}
	cfg := gen.Config{Mode: mode, Prefix: *prefixFlag}

	// Advertise proto3 optional support so protoc lets us see those fields.
	plugin.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)

	for _, file := range plugin.Files {
		if !file.Generate {
			continue
		}
		if err := gen.GenerateFile(plugin, file, cfg); err != nil {
			plugin.Error(err)
		}
	}

	out, err := proto.Marshal(plugin.Response())
	if err != nil {
		fail("marshal CodeGeneratorResponse: %v", err)
	}
	if _, err := os.Stdout.Write(out); err != nil {
		fail("write stdout: %v", err)
	}
}

func fail(format string, args ...any) {
	fmt.Fprintf(os.Stderr, "protoc-gen-tarantool: "+format+"\n", args...)
	os.Exit(1)
}