twirp 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,14 +0,0 @@
1
- syntax = "proto3";
2
- package example;
3
-
4
- service Haberdasher {
5
- rpc HelloWorld(HelloWorldRequest) returns (HelloWorldResponse);
6
- }
7
-
8
- message HelloWorldRequest {
9
- string name = 1;
10
- }
11
-
12
- message HelloWorldResponse {
13
- string message = 1;
14
- }
@@ -1,14 +0,0 @@
1
- require 'rack'
2
- require_relative 'gen/haberdasher_pb.rb'
3
- require_relative 'gen/haberdasher_twirp.rb'
4
-
5
- class HaberdasherHandler
6
- def hello_world(req, env)
7
- {message: "Hello #{req.name}"}
8
- end
9
- end
10
-
11
- handler = HaberdasherHandler.new()
12
- service = Example::HaberdasherService.new(handler)
13
-
14
- Rack::Handler::WEBrick.run service
@@ -1,259 +0,0 @@
1
- package main
2
-
3
- import (
4
- "bytes"
5
- "flag"
6
- "fmt"
7
- "io"
8
- "io/ioutil"
9
- "log"
10
- "os"
11
- "path"
12
- "strings"
13
- "unicode"
14
-
15
- "github.com/golang/protobuf/proto"
16
- "github.com/golang/protobuf/protoc-gen-go/descriptor"
17
- plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
18
- )
19
-
20
- const Version = "v5.2.0"
21
-
22
- func main() {
23
- versionFlag := flag.Bool("version", false, "print version and exit")
24
- flag.Parse()
25
- if *versionFlag {
26
- fmt.Println(Version)
27
- os.Exit(0)
28
- }
29
-
30
- g := newGenerator()
31
- Main(g)
32
- }
33
-
34
- type Generator interface {
35
- Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse
36
- }
37
-
38
- func Main(g Generator) {
39
- req := readGenRequest(os.Stdin)
40
- resp := g.Generate(req)
41
- writeResponse(os.Stdout, resp)
42
- }
43
-
44
- type generator struct {
45
- output *bytes.Buffer
46
- }
47
-
48
- func newGenerator() *generator {
49
- return &generator{output: new(bytes.Buffer)}
50
- }
51
-
52
- func (g *generator) Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse {
53
-
54
- resp := new(plugin.CodeGeneratorResponse)
55
- for _, name := range in.FileToGenerate {
56
- for _, f := range in.ProtoFile {
57
- if f.GetName() == name {
58
- respFile := g.generateFile(f)
59
- if respFile != nil {
60
- resp.File = append(resp.File, respFile)
61
- }
62
- continue
63
- }
64
- }
65
- }
66
-
67
- return resp
68
- }
69
-
70
- func (g *generator) generateFile(file *descriptor.FileDescriptorProto) *plugin.CodeGeneratorResponse_File {
71
- indent := ""
72
- pkgName := pkgName(file)
73
- g.P(`# Code generated by protoc-gen-twirp_ruby, DO NOT EDIT.`)
74
- g.P(`require 'twirp'`)
75
- g.P(``)
76
- if pkgName != "" {
77
- g.P(fmt.Sprintf("module %s", CamelCase(pkgName)))
78
- indent = indent + " "
79
- }
80
- for i, service := range file.Service {
81
- serviceName := serviceName(service)
82
- g.P(fmt.Sprintf("%sclass %sService < Twirp::Service", indent, CamelCase(serviceName)))
83
- if pkgName != "" {
84
- g.P(fmt.Sprintf(`%s package "%s"`, indent, pkgName))
85
- }
86
- g.P(fmt.Sprintf(`%s service "%s"`, indent, serviceName))
87
- for _, method := range service.GetMethod() {
88
- methName := methodName(method)
89
- inputName := methodInputName(method)
90
- outputName := methodOutputName(method)
91
- g.P(fmt.Sprintf(`%s rpc :%s, %s, %s, :handler_method => :%s`,
92
- indent, methName, inputName, outputName, SnakeCase(methName)))
93
- }
94
- g.P(fmt.Sprintf(`%send`, indent))
95
- if i < len(file.Service)-1 {
96
- g.P(``)
97
- }
98
- }
99
- if pkgName != "" {
100
- g.P(`end`)
101
- }
102
-
103
- resp := new(plugin.CodeGeneratorResponse_File)
104
- resp.Name = proto.String(rubyFileName(file))
105
- resp.Content = proto.String(g.output.String())
106
- g.output.Reset()
107
-
108
- return resp
109
- }
110
-
111
- func (g *generator) P(args ...string) {
112
- for _, v := range args {
113
- g.output.WriteString(v)
114
- }
115
- g.output.WriteByte('\n')
116
- }
117
-
118
- func rubyFileName(f *descriptor.FileDescriptorProto) string {
119
- name := *f.Name
120
- if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" {
121
- name = name[:len(name)-len(ext)]
122
- }
123
- name += "_twirp.rb"
124
- return name
125
- }
126
-
127
- func pkgName(file *descriptor.FileDescriptorProto) string {
128
- return file.GetPackage()
129
- }
130
-
131
- func serviceName(service *descriptor.ServiceDescriptorProto) string {
132
- return service.GetName()
133
- }
134
-
135
- func methodName(method *descriptor.MethodDescriptorProto) string {
136
- return method.GetName()
137
- }
138
-
139
- // methodInputName returns the basename of the input type of a method in snake
140
- // case.
141
- func methodInputName(meth *descriptor.MethodDescriptorProto) string {
142
- fullName := meth.GetInputType()
143
- split := strings.Split(fullName, ".")
144
- return split[len(split)-1]
145
- }
146
-
147
- // methodInputName returns the basename of the input type of a method in snake
148
- // case.
149
- func methodOutputName(meth *descriptor.MethodDescriptorProto) string {
150
- fullName := meth.GetOutputType()
151
- split := strings.Split(fullName, ".")
152
- return split[len(split)-1]
153
- }
154
-
155
- func Fail(msgs ...string) {
156
- s := strings.Join(msgs, " ")
157
- log.Print("error:", s)
158
- os.Exit(1)
159
- }
160
-
161
- // SnakeCase converts a string from CamelCase to snake_case.
162
- func SnakeCase(s string) string {
163
- var buf bytes.Buffer
164
- for i, r := range s {
165
- if unicode.IsUpper(r) && i > 0 {
166
- fmt.Fprintf(&buf, "_")
167
- }
168
- r = unicode.ToLower(r)
169
- fmt.Fprintf(&buf, "%c", r)
170
- }
171
- return buf.String()
172
- }
173
-
174
- func readGenRequest(r io.Reader) *plugin.CodeGeneratorRequest {
175
- data, err := ioutil.ReadAll(os.Stdin)
176
- if err != nil {
177
- Fail(err.Error(), "reading input")
178
- }
179
-
180
- req := new(plugin.CodeGeneratorRequest)
181
- if err = proto.Unmarshal(data, req); err != nil {
182
- Fail(err.Error(), "parsing input proto")
183
- }
184
-
185
- if len(req.FileToGenerate) == 0 {
186
- Fail("no files to generate")
187
- }
188
-
189
- return req
190
- }
191
-
192
- func writeResponse(w io.Writer, resp *plugin.CodeGeneratorResponse) {
193
- data, err := proto.Marshal(resp)
194
- if err != nil {
195
- Fail(err.Error(), "marshaling response")
196
- }
197
- _, err = w.Write(data)
198
- if err != nil {
199
- Fail(err.Error(), "writing response")
200
- }
201
- }
202
-
203
- // CamelCase converts a string from snake_case to CamelCased.
204
- //
205
- // If there is an interior underscore followed by a lower case letter, drop the
206
- // underscore and convert the letter to upper case. There is a remote
207
- // possibility of this rewrite causing a name collision, but it's so remote
208
- // we're prepared to pretend it's nonexistent - since the C++ generator
209
- // lowercases names, it's extremely unlikely to have two fields with different
210
- // capitalizations. In short, _my_field_name_2 becomes XMyFieldName_2.
211
- func CamelCase(s string) string {
212
- if s == "" {
213
- return ""
214
- }
215
- t := make([]byte, 0, 32)
216
- i := 0
217
- if s[0] == '_' {
218
- // Need a capital letter; drop the '_'.
219
- t = append(t, 'X')
220
- i++
221
- }
222
- // Invariant: if the next letter is lower case, it must be converted
223
- // to upper case.
224
- //
225
- // That is, we process a word at a time, where words are marked by _ or upper
226
- // case letter. Digits are treated as words.
227
- for ; i < len(s); i++ {
228
- c := s[i]
229
- if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
230
- continue // Skip the underscore in s.
231
- }
232
- if isASCIIDigit(c) {
233
- t = append(t, c)
234
- continue
235
- }
236
- // Assume we have a letter now - if not, it's a bogus identifier. The next
237
- // word is a sequence of characters that must start upper case.
238
- if isASCIILower(c) {
239
- c ^= ' ' // Make it a capital letter.
240
- }
241
- t = append(t, c) // Guaranteed not lower case.
242
- // Accept lower case sequence that follows.
243
- for i+1 < len(s) && isASCIILower(s[i+1]) {
244
- i++
245
- t = append(t, s[i])
246
- }
247
- }
248
- return string(t)
249
- }
250
-
251
- // Is c an ASCII lower-case letter?
252
- func isASCIILower(c byte) bool {
253
- return 'a' <= c && c <= 'z'
254
- }
255
-
256
- // Is c an ASCII digit?
257
- func isASCIIDigit(c byte) bool {
258
- return '0' <= c && c <= '9'
259
- }