forked from alpancs/protoc-gen-pubsub-schema
-
Notifications
You must be signed in to change notification settings - Fork 0
/
content_builder.go
78 lines (67 loc) · 2.54 KB
/
content_builder.go
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
package main
import (
"errors"
"fmt"
"strings"
"golang.org/x/exp/slices"
"google.golang.org/protobuf/types/descriptorpb"
)
type contentBuilder struct {
*responseBuilder
file *descriptorpb.FileDescriptorProto
output *strings.Builder
}
func newContentBuilder(b *responseBuilder, file *descriptorpb.FileDescriptorProto) *contentBuilder {
return &contentBuilder{b, file, new(strings.Builder)}
}
func (b *contentBuilder) build() (string, error) {
if b.file == nil {
return "", errors.New("contentBuilder.build(): protoFile is nil")
}
if len(b.file.GetMessageType()) != 1 {
return "", errors.New(b.file.GetName() + ": only one top-level type may be defined in a file (see https://cloud.google.com/pubsub/docs/schemas#schema_types). use nested types or imports (see https://developers.google.com/protocol-buffers/docs/proto)")
}
fmt.Fprintf(b.output, "// Code generated by protoc-gen-pubsub-schema. DO NOT EDIT.\n")
fmt.Fprintf(b.output, "// versions:\n")
fmt.Fprintf(b.output, "// protoc-gen-pubsub-schema v1.6.0\n")
fmt.Fprintf(b.output, "// source: %s\n\n", b.file.GetName())
fmt.Fprintf(b.output, "syntax = \"%s\";\n\n", b.schemaSyntax)
fmt.Fprintf(b.output, "package %s;\n", b.file.GetPackage())
b.buildMessages(0, b.file.GetMessageType())
b.buildEnums(0, b.file.GetEnumType())
return b.output.String(), nil
}
func (b *contentBuilder) buildMessages(level int, messages []*descriptorpb.DescriptorProto) {
built := make(map[*descriptorpb.DescriptorProto]bool)
for _, message := range messages {
if built[message] {
continue
}
fmt.Fprintln(b.output)
newMessageBuilder(b, level, message).build()
built[message] = true
}
}
func (b *contentBuilder) buildEnums(level int, enums []*descriptorpb.EnumDescriptorProto) {
built := make(map[*descriptorpb.EnumDescriptorProto]bool)
for _, enum := range enums {
if built[enum] {
continue
}
fmt.Fprintln(b.output)
fmt.Fprintf(b.output, "%senum %s {\n", buildIndent(level), enum.GetName())
for _, value := range enum.GetValue() {
fmt.Fprintf(b.output, "%s%s = %d;\n", buildIndent(level+1), value.GetName(), value.GetNumber())
}
fmt.Fprintf(b.output, "%s}\n", buildIndent(level))
built[enum] = true
}
}
func (b *contentBuilder) isInternalDefinition(field *descriptorpb.FieldDescriptorProto) bool {
return (field.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE ||
field.GetType() == descriptorpb.FieldDescriptorProto_TYPE_ENUM) &&
slices.Contains(b.fileTypeNames[b.file], field.GetTypeName())
}
func buildIndent(level int) string {
return strings.Repeat(" ", level)
}