twirp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
- }