stark 0.7.0 → 0.8.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.
@@ -12,12 +12,10 @@ module Stark
12
12
 
13
13
  @stream = stream
14
14
 
15
-
15
+ o "require 'set'"
16
16
  o "require 'stark/client'"
17
- o "require 'stark/struct'"
18
- o "require 'stark/field'"
19
- o "require 'stark/converters'"
20
17
  o "require 'stark/processor'"
18
+ o "require 'stark/struct'"
21
19
  o "require 'stark/exception'"
22
20
  end
23
21
 
@@ -27,6 +25,7 @@ module Stark
27
25
  end
28
26
 
29
27
  def close
28
+ write_protocol
30
29
  if @namespace
31
30
  outdent
32
31
  o "end"
@@ -34,109 +33,74 @@ module Stark
34
33
  end
35
34
 
36
35
  def process_namespace(ns)
37
- @namespace = ns.namespace if ns.lang == "rb"
38
- o "module #{ns.namespace}"
36
+ return unless [nil, 'rb'].include?(ns.lang)
37
+ @namespace = ns.namespace.gsub('.', '::')
38
+ parts = @namespace.split('::')
39
+ if parts.length > 1
40
+ 0.upto(parts.length - 2) do |i|
41
+ o "module #{parts[0..i].join('::')}; end unless defined?(#{parts[0..i].join('::')})"
42
+ end
43
+ end
44
+ o
45
+ o "module #{@namespace}"
39
46
  indent
40
47
  end
41
48
 
42
49
  def process_include(inc)
50
+ raise NotImplementedError, "include not implemented"
43
51
  end
44
52
 
45
53
  def process_enum(enum)
54
+ @enums[enum.name] = enum
46
55
  e = "Enum_#{enum.name}"
47
56
  o "#{e} = Hash.new { |h,k| p [:bad, k]; h[k] = -1 }"
48
-
49
57
  idx = 0
50
58
  enum.values.each do |f|
51
59
  o "#{e}[#{idx}] = :'#{f}'"
52
60
  o "#{e}[:'#{f}'] = #{idx}"
53
61
  idx += 1
54
62
  end
55
-
56
- @enums[enum.name] = enum
57
63
  end
58
64
 
59
- def converter(t)
60
- if t.kind_of? Stark::Parser::AST::List
61
- "Stark::Converters::List.new(#{converter(t.value)})"
62
- elsif BUILTINS.include? t.downcase
63
- "Stark::Converters::#{t.upcase}"
64
- elsif desc = @structs[t]
65
- "Stark::Converters::Struct.new(#{t})"
66
- elsif desc = @enums[t]
67
- "Stark::Converters::Enum.new(Enum_#{t})"
68
- else
69
- raise "Blah"
65
+ def write_field_declarations(fields)
66
+ max_field_len = fields.inject(0) {|max,f| f.name.length > max ? f.name.length : max }
67
+ max_index_len = fields.inject(0) {|max,f| f.index.to_s.length > max ? f.index.to_s.length : max }
68
+
69
+ current_index = 1
70
+ fields.each do |f|
71
+ if f.index != current_index
72
+ o "field_number #{f.index}"
73
+ current_index = f.index
74
+ end
75
+ current_index += 1
76
+ o("attr_accessor :%-*s # %*s: %s" % [max_field_len, f.name, max_index_len, f.index, object_type(f.type)])
70
77
  end
71
78
  end
72
79
 
73
80
  def process_struct(str)
74
81
  @structs[str.name] = str
75
82
 
83
+ o
76
84
  o "class #{str.name} < Stark::Struct"
77
85
  indent
78
- o "Fields = {"
79
- indent
80
-
81
- fields = str.fields.map do |f|
82
- c = converter f.type
83
- "#{f.index} => Stark::Field.new(#{f.index}, '#{f.name}', #{c})"
84
- end
85
-
86
- o " #{fields.join(', ')}"
87
-
88
- outdent
89
- o "}"
90
-
91
- str.fields.each do |f|
92
- o "def #{f.name}; @fields['#{f.name}']; end"
93
- end
94
-
86
+ write_field_declarations str.fields
95
87
  outdent
96
88
  o "end"
97
-
98
89
  end
99
90
 
100
- BUILTINS = %w!bool byte i16 i32 i64 double string!
101
-
102
91
  def process_exception(str)
103
92
  @exceptions[str.name] = str
104
93
 
94
+ o
105
95
  o "class #{str.name} < Stark::Exception"
106
96
  indent
107
-
108
- o "class Struct < Stark::Struct"
109
- indent
110
- o "Fields = {"
111
- indent
112
-
113
- fields = str.fields.map do |f|
114
- c = converter f.type
115
- "#{f.index} => Stark::Field.new(#{f.index}, '#{f.name}', #{c})"
116
- end
117
-
118
- o " #{fields.join(', ')}"
119
-
120
- outdent
121
- o "}"
122
-
123
- str.fields.each do |f|
124
- o "def #{f.name}; @fields['#{f.name}']; end"
125
- end
126
-
127
- outdent
128
- o "end"
129
-
130
- str.fields.each do |f|
131
- o "def #{f.name}; @struct.#{f.name}; end"
132
- end
133
-
97
+ write_field_declarations str.fields
134
98
  outdent
135
99
  o "end"
136
100
  end
137
101
 
138
- def o(str)
139
- @stream.print(" " * @indent)
102
+ def o(str = nil)
103
+ @stream.print(" " * @indent) if str
140
104
  @stream.puts str
141
105
  end
142
106
 
@@ -156,6 +120,7 @@ module Stark
156
120
  'i32' => "::Thrift::Types::I32",
157
121
  'i64' => "::Thrift::Types::I64",
158
122
  'string' => '::Thrift::Types::STRING',
123
+ 'binary' => '::Thrift::Types::STRING',
159
124
  'struct' => '::Thrift::Types::STRUCT',
160
125
  'map' => '::Thrift::Types::MAP',
161
126
  'set' => '::Thrift::Types::SET',
@@ -170,6 +135,7 @@ module Stark
170
135
  'i32' => "read_i32",
171
136
  'i64' => "read_i64",
172
137
  'string' => 'read_string',
138
+ 'binary' => 'read_string',
173
139
  }
174
140
 
175
141
  WriteFunc = {
@@ -180,6 +146,7 @@ module Stark
180
146
  'i32' => "write_i32",
181
147
  'i64' => "write_i64",
182
148
  'string' => 'write_string',
149
+ 'binary' => 'write_string',
183
150
  }
184
151
 
185
152
  def type(t)
@@ -187,7 +154,7 @@ module Stark
187
154
  end
188
155
 
189
156
  def wire_type(t)
190
- return "::Thrift::Types::STRUCT" if @structs[t]
157
+ return "::Thrift::Types::STRUCT" if @structs[t] || @exceptions[t]
191
158
  return "::Thrift::Types::I32" if @enums[t]
192
159
 
193
160
  case t
@@ -202,9 +169,23 @@ module Stark
202
169
  end
203
170
  end
204
171
 
172
+ def wire_type_and_ruby_type(t)
173
+ return "::Thrift::Types::STRUCT, #{t}" if @structs[t] || @exceptions[t]
174
+ return "::Thrift::Types::I32, Enum_#{t}" if @enums[t]
175
+ wire_type(t)
176
+ end
177
+
205
178
  def object_type(t)
206
- return t if @structs[t]
207
- type t
179
+ case t
180
+ when Stark::Parser::AST::Map
181
+ "map<#{object_type(t.key)},#{object_type(t.value)}>"
182
+ when Stark::Parser::AST::List
183
+ "list<#{object_type(t.value)}>"
184
+ when Stark::Parser::AST::Set
185
+ "set<#{object_type(t.value)}>"
186
+ else
187
+ t
188
+ end
208
189
  end
209
190
 
210
191
  def read_func(t)
@@ -215,146 +196,160 @@ module Stark
215
196
  WriteFunc[t] || raise("unknown type - #{t}")
216
197
  end
217
198
 
218
- def write_field(ft, name, idx)
219
- if desc = @structs[ft]
220
- o "op.write_field_begin '#{name}', ::Thrift::Types::STRUCT, #{idx}"
221
- output_struct desc, name
222
- o "op.write_field_end"
199
+ def read_type(t, lhs, found_type = 'rtype')
200
+ o "#{lhs} = expect ip, #{wire_type(t)}, #{found_type} do"
201
+ indent
202
+ if desc = @structs[t]
203
+ o "read_#{desc.name}(ip)"
204
+ elsif desc = @enums[t]
205
+ o "Enum_#{desc.name}[ip.read_i32]"
206
+ elsif t.kind_of? Stark::Parser::AST::Map
207
+ o "expect_map ip, #{wire_type(t.key)}, #{wire_type(t.value)} do |kt,vt,size|"
208
+ indent
209
+ o "{}.tap do |_hash|"
210
+ indent
211
+ o "size.times do"
212
+ indent
213
+ read_type(t.key, "k", "kt")
214
+ read_type(t.value, "v", "vt")
215
+ o "_hash[k] = v"
216
+ outdent
217
+ o "end"
218
+ outdent
219
+ o "end"
220
+ outdent
221
+ o "end"
222
+ elsif t.kind_of? Stark::Parser::AST::List
223
+ o "expect_list ip, #{wire_type(t.value)} do |vt,size|"
224
+ indent
225
+ o "Array.new(size) do"
226
+ indent
227
+ read_type t.value, "_elem", "vt"
228
+ outdent
229
+ o "end"
230
+ outdent
231
+ o "end"
232
+ elsif t.kind_of? Stark::Parser::AST::Set
233
+ o "expect_set ip, #{wire_type(t.value)} do |vt,size|"
234
+ indent
235
+ o "_arr = Array.new(size) do"
236
+ indent
237
+ read_type t.value, "element", "vt"
238
+ o "element"
239
+ outdent
240
+ o "end"
241
+ o "::Set.new(_arr)"
242
+ outdent
243
+ o "end"
244
+ else
245
+ o "ip.#{read_func(t)}"
246
+ end
247
+ outdent
248
+ o "end"
249
+ end
250
+
251
+ def write_type(ft, name)
252
+ if desc = (@structs[ft] || @exceptions[ft])
253
+ o "write_#{desc.name} op, #{name}"
223
254
  elsif desc = @enums[ft]
224
- o "op.write_field_begin '#{name}', ::Thrift::Types::I32, #{idx}"
225
255
  o "op.write_i32 Enum_#{desc.name}[#{name}.to_sym]"
226
-
227
- o "op.write_field_end"
228
256
  elsif ft.kind_of? Stark::Parser::AST::Map
229
257
  o "#{name} = hash_cast #{name}"
230
- o "op.write_field_begin '#{name}', ::Thrift::Types::MAP, #{idx}"
231
258
  o "op.write_map_begin(#{wire_type(ft.key)}, #{wire_type(ft.value)}, #{name}.size)"
232
-
233
259
  o "#{name}.each do |k,v|"
234
260
  indent
235
- o "op.#{write_func(ft.key)} k"
236
- o "op.#{write_func(ft.value)} v"
261
+ write_type ft.key, "k"
262
+ write_type ft.value, "v"
237
263
  outdent
238
264
  o "end"
239
-
240
265
  o "op.write_map_end"
241
- o "op.write_field_end"
242
266
  elsif ft.kind_of? Stark::Parser::AST::List
243
267
  o "#{name} = Array(#{name})"
244
- o "op.write_field_begin '#{name}', ::Thrift::Types::LIST, #{idx}"
245
268
  o "op.write_list_begin(#{wire_type(ft.value)}, #{name}.size)"
246
- o "#{name}.each { |v| op.#{write_func(ft.value)}(v) }"
269
+ o "#{name}.each do |v|"
270
+ indent
271
+ write_type ft.value, "v"
272
+ outdent
273
+ o "end"
247
274
  o "op.write_list_end"
248
-
249
- o "op.write_field_end"
275
+ elsif ft.kind_of? Stark::Parser::AST::Set
276
+ o "#{name} = Set.new(#{name})"
277
+ o "op.write_list_begin(#{wire_type(ft.value)}, #{name}.size)"
278
+ o "#{name}.each do |v|"
279
+ indent
280
+ write_type ft.value, "v"
281
+ outdent
282
+ o "end"
283
+ o "op.write_set_end"
250
284
  elsif ft != "void"
251
- o "op.write_field_begin '#{name}', #{type(ft)}, #{idx}"
252
285
  o "op.#{write_func(ft)} #{name}"
253
- o "op.write_field_end"
254
286
  end
255
-
256
287
  end
257
288
 
258
- def output_struct(desc, obj)
259
- o "op.write_struct_begin '#{desc.name}'"
260
-
261
- desc.fields.each do |f|
262
- o "#{f.name} = #{obj}.#{f.name}"
263
- write_field f.type, f.name, f.index
264
- end
265
-
266
- o "op.write_field_stop"
267
- o "op.write_struct_end"
289
+ def write_field(ft, name, idx)
290
+ o "op.write_field_begin '#{name}', #{wire_type(ft)}, #{idx}"
291
+ write_type ft, name
292
+ o "op.write_field_end"
268
293
  end
269
294
 
270
295
  def write_processor(serv)
271
296
  o "class Processor < Stark::Processor"
272
297
  indent
298
+ o "include Protocol"
273
299
 
274
300
  serv.functions.each do |func|
301
+ o
275
302
  o "def process_#{func.name}(seqid, ip, op)"
276
303
  indent
277
304
 
278
305
  o "ip.read_struct_begin"
279
306
  args = Array(func.arguments)
280
- o "args = Array.new(#{args.size})"
281
-
282
- args.each do |arg|
283
- if desc = @structs[arg.type]
284
- o "_, rtype, rid = ip.read_field_begin"
285
- o "if rtype != #{wire_type(arg.type)}"
286
- o " handle_unexpected rtype"
287
- o "else"
288
- o " args[#{arg.index - 1}] = read_struct ip, rtype, rid, #{desc.name}"
289
- o "end"
290
- o "ip.read_field_end"
291
- elsif desc = @enums[arg.type]
292
- o "_, rtype, _ = ip.read_field_begin"
293
- o "if rtype != #{wire_type(arg.type)}"
294
- o " handle_unexpected rtype"
295
- o "else"
296
- o " args[#{arg.index - 1}] = Enum_#{desc.name}[ip.read_i32]"
297
- o "end"
298
- o "ip.read_field_end"
299
-
300
- elsif arg.type.kind_of? Stark::Parser::AST::Map
301
- ft = arg.type
302
-
303
- o "_, rtype, _ = ip.read_field_begin"
304
- o "if rtype != #{wire_type(arg.type)}"
305
- o " handle_unexpected rtype"
306
- o "else"
307
- o " kt, vt, size = ip.read_map_begin"
308
- o " if kt == #{wire_type(ft.key)} && vt == #{wire_type(ft.value)}"
309
- o " result = {}"
310
- o " size.times do"
311
- o " result[ip.#{read_func(ft.key)}] = ip.#{read_func(ft.value)}"
312
- o " end"
313
- o " args[#{arg.index - 1}] = result"
314
- o " else"
315
- o " handle_bad_map size"
316
- o " end"
317
- o " ip.read_map_end"
318
- o "end"
319
- o "ip.read_field_end"
320
- elsif arg.type.kind_of? Stark::Parser::AST::List
321
- ft = arg.type
322
- o "_, rtype, _ = ip.read_field_begin"
323
- o "if rtype == ::Thrift::Types::LIST"
324
- o " vt, size = ip.read_list_begin"
325
- o " if vt == #{wire_type(ft.value)}"
326
- o " args[#{arg.index - 1}] = Array.new(size) { |n| ip.#{read_func(ft.value)} }"
327
- o " else"
328
- o " handle_bad_list size"
329
- o " end"
330
- o " ip.read_list_end"
331
- o "else"
332
- o " handle_unexpected rtype"
333
- o "end"
334
- o "ip.read_field_end"
335
- else
336
- o "_, rtype, _ = ip.read_field_begin"
337
- o "if rtype == #{type(arg.type)}"
338
- o " args[#{arg.index - 1}]= ip.#{read_func(arg.type)}"
339
- o "else"
340
- o " handle_unexpected rtype"
341
- o "end"
342
- o "ip.read_field_end"
307
+ o "fields = {}"
308
+
309
+ o "while true"
310
+ o " _, ftype, fid = ip.read_field_begin"
311
+ o " break if ftype == ::Thrift::Types::STOP"
312
+
313
+ if args.empty?
314
+ o " ip.skip ftype"
315
+ else
316
+ o " case fid"
317
+ args.each do |arg|
318
+ o " when #{arg.index}"
319
+ indent; indent
320
+ read_type arg.type, "fields[#{arg.index}]", "ftype"
321
+ outdent; outdent
343
322
  end
323
+ o " else"
324
+ o " ip.skip ftype"
325
+ o " end"
344
326
  end
345
-
346
- o "_, rtype, _ = ip.read_field_begin"
347
- o "fail unless rtype == ::Thrift::Types::STOP"
327
+ o " ip.read_field_end"
328
+ o "end"
348
329
  o "ip.read_struct_end"
349
330
  o "ip.read_message_end"
350
331
 
351
- if t = func.throws
352
- o "result = check_raise_specific('#{func.name}', seqid, op, #{t.first.type}) do"
353
- o " @handler.#{func.name}(*args)"
354
- o "end"
355
-
356
- o "return unless result"
332
+ o "args = #{args.map(&:index).inspect}.inject([]) {|arr,i| arr << fields[i] }"
357
333
 
334
+ if t = func.throws
335
+ o "begin"
336
+ indent
337
+ o "result = @handler.#{func.name}(*args)"
338
+ outdent
339
+ t.each do |ex|
340
+ o "rescue #{ex.type} => ex#{ex.index}"
341
+ indent
342
+ o "op.write_message_begin '#{func.name}', ::Thrift::MessageTypes::REPLY, seqid"
343
+ o "op.write_struct_begin '#{func.name}_result'"
344
+ write_field ex.type, "ex#{ex.index}", ex.index
345
+ o "op.write_field_stop"
346
+ o "op.write_struct_end"
347
+ o "op.write_message_end"
348
+ o "op.trans.flush"
349
+ o "return"
350
+ outdent
351
+ end
352
+ o "end"
358
353
  else
359
354
  o "result = @handler.#{func.name}(*args)"
360
355
  end
@@ -366,12 +361,19 @@ module Stark
366
361
  next
367
362
  end
368
363
 
364
+ ft = func.return_type
365
+ o "result = value_for_write(result, #{wire_type_and_ruby_type(ft)})" if ft != "void"
366
+
369
367
  o "op.write_message_begin '#{func.name}', ::Thrift::MessageTypes::REPLY, seqid"
370
368
  o "op.write_struct_begin '#{func.name}_result'"
371
369
 
372
- ft = func.return_type
373
-
374
- write_field ft, 'result', 0
370
+ if ft != "void"
371
+ o "if result"
372
+ indent
373
+ write_field ft, 'result', 0
374
+ outdent
375
+ o "end"
376
+ end
375
377
 
376
378
  o "op.write_field_stop"
377
379
  o "op.write_struct_end"
@@ -387,31 +389,69 @@ module Stark
387
389
  o "end"
388
390
  end
389
391
 
390
- def process_service(serv)
391
- o "module #{serv.name}"
392
- indent
393
- o "class Client < Stark::Client"
392
+ def write_protocol
393
+ o
394
+ o "module Protocol"
394
395
  indent
396
+ @structs.merge(@exceptions).each do |name, struct|
397
+ o
398
+ o "def read_#{name}(ip)"
399
+ indent
400
+ o "obj = #{name}.new"
401
+ o "ip.read_struct_begin"
395
402
 
396
- o "Functions = {}"
397
- serv.functions.each do |func|
398
- o "Functions[\"#{func.name}\"] = {"
399
-
400
- o " :args => {"
403
+ o "while true"
404
+ o " _, ftype, fid = ip.read_field_begin"
405
+ o " break if ftype == ::Thrift::Types::STOP"
401
406
 
402
- mapped_args = Array(func.arguments).map do |a|
403
- "#{a.index} => #{wire_type(a.type)}"
407
+ o " case fid"
408
+ struct.fields.each do |f|
409
+ o " when #{f.index}"
410
+ indent; indent
411
+ read_type f.type, "obj.#{f.name}", 'ftype'
412
+ outdent; outdent
404
413
  end
414
+ o " else"
415
+ o " ip.skip ftype"
416
+ o " end"
417
+ o " ip.read_field_end"
418
+ o "end"
405
419
 
406
- o " #{mapped_args.join(', ')}"
420
+ o "ip.read_struct_end"
421
+ o "obj"
422
+ outdent
423
+ o "end"
424
+ o
425
+ o "def write_#{name}(op, str)"
426
+ indent
427
+ o "op.write_struct_begin '#{name}'"
407
428
 
408
- o " }"
409
- o " }"
429
+ struct.fields.each do |f|
430
+ o "if #{f.name} = value_for_write(str.#{f.name}, #{wire_type_and_ruby_type(f.type)})"
431
+ indent
432
+ write_field f.type, f.name, f.index
433
+ outdent
434
+ o "end"
435
+ end
436
+
437
+ o "op.write_field_stop"
438
+ o "op.write_struct_end"
439
+ outdent
440
+ o "end"
410
441
  end
442
+ outdent
443
+ o "end"
444
+ end
445
+
446
+ def write_client(serv)
447
+ o "class Client < Stark::Client"
448
+ indent
449
+ o "include Protocol"
411
450
 
412
451
  serv.functions.each do |func|
413
452
  names = Array(func.arguments).map { |f| f.name }.join(", ")
414
453
 
454
+ o
415
455
  o "def #{func.name}(#{names})"
416
456
  indent
417
457
  o "op = @oprot"
@@ -419,6 +459,7 @@ module Stark
419
459
  o "op.write_struct_begin \"#{func.name}_args\""
420
460
 
421
461
  Array(func.arguments).each do |arg|
462
+ o "#{arg.name} = value_for_write #{arg.name}, #{wire_type_and_ruby_type(arg.type)}"
422
463
  write_field arg.type, arg.name, arg.index
423
464
  end
424
465
 
@@ -444,68 +485,32 @@ module Stark
444
485
  o "_, rtype, rid = ip.read_field_begin"
445
486
 
446
487
  if t = func.throws
447
- o "if rid == 1"
448
- o " handle_throw #{t.first.type}"
488
+ o "case rid"
489
+ t.each do |ex|
490
+ o "when #{ex.index}"
491
+ o " _ex = read_#{ex.type}(ip)"
492
+ o " ip.read_field_end"
493
+ o " _, rtype, _ = ip.read_field_begin"
494
+ o " fail if rtype != ::Thrift::Types::STOP"
495
+ o " ip.read_struct_end"
496
+ o " ip.read_message_end"
497
+ o " raise _ex"
498
+ end
449
499
  o "end"
450
500
  end
451
501
 
452
- o "fail unless rid == 0"
453
-
454
502
  o "result = nil"
455
503
 
456
- if func.return_type != "void"
457
- if desc = @structs[func.return_type]
458
- o "if rtype != #{wire_type(func.return_type)}"
459
- o " handle_unexpected rtype"
460
- o "else"
461
- o " result = read_generic rtype, rid, #{desc.name}"
462
- o "end"
463
- elsif desc = @enums[func.return_type]
464
- o "if rtype != #{wire_type(func.return_type)}"
465
- o " handle_unexpected rtype"
466
- o "else"
467
- o " result = Enum_#{desc.name}[ip.read_i32]"
468
- o "end"
469
-
470
- elsif func.return_type.kind_of? Stark::Parser::AST::Map
471
- ft = func.return_type
472
-
473
- o "if rtype != #{wire_type(func.return_type)}"
474
- o " handle_unexpected rtype"
475
- o "else"
476
- o " kt, vt, size = ip.read_map_begin"
477
- o " if kt == #{wire_type(ft.key)} && vt == #{wire_type(ft.value)}"
478
- o " result = {}"
479
- o " size.times do"
480
- o " result[ip.#{read_func(ft.key)}] = ip.#{read_func(ft.value)}"
481
- o " end"
482
- o " else"
483
- o " handle_bad_map size"
484
- o " end"
485
- o " ip.read_map_end"
486
- o "end"
487
- elsif func.return_type.kind_of? Stark::Parser::AST::List
488
- ft = func.return_type
489
- o "if rtype == ::Thrift::Types::LIST"
490
- o " vt, size = ip.read_list_begin"
491
- o " if vt == #{wire_type(ft.value)}"
492
- o " result = Array.new(size) { |n| ip.#{read_func(ft.value)} }"
493
- o " else"
494
- o " handle_bad_list size"
495
- o " end"
496
- o " ip.read_list_end"
497
- o "else"
498
- o " handle_unexpected rtype"
499
- o "end"
500
- else
501
- o "if rtype == #{type(func.return_type)}"
502
- o " result = ip.#{read_func(func.return_type)}"
503
- o "else"
504
- o " handle_unexpected rtype"
505
- o "end"
506
- end
504
+ o "fail unless rid == 0"
507
505
 
508
- o "_, rtype, rid = ip.read_field_begin unless rtype == ::Thrift::Types::STOP"
506
+ if func.return_type != "void"
507
+ o "if rtype != ::Thrift::Types::STOP"
508
+ indent
509
+ read_type func.return_type, "result"
510
+ o "ip.read_field_end"
511
+ o "_, rtype, rid = ip.read_field_begin"
512
+ outdent
513
+ o "end"
509
514
  end
510
515
 
511
516
  o "fail if rtype != ::Thrift::Types::STOP"
@@ -521,7 +526,21 @@ module Stark
521
526
 
522
527
  outdent
523
528
  o "end"
529
+ end
530
+
531
+ def process_service(serv)
532
+ unless @protocol_declared
533
+ o
534
+ o "module Protocol; end"
535
+ @protocol_declared = true
536
+ end
537
+
538
+ o
539
+ o "module #{serv.name}"
540
+ indent
524
541
 
542
+ write_client serv
543
+ o
525
544
  write_processor serv
526
545
 
527
546
  outdent