// 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) }