thrift-mavericks 0.8.0 → 0.9.0.1

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.
Files changed (59) hide show
  1. checksums.yaml +8 -8
  2. data/ext/binary_protocol_accelerated.c +21 -2
  3. data/ext/bytes.c +36 -0
  4. data/ext/bytes.h +31 -0
  5. data/ext/compact_protocol.c +24 -7
  6. data/ext/constants.h +5 -5
  7. data/ext/extconf.rb +3 -1
  8. data/ext/memory_buffer.c +11 -8
  9. data/ext/protocol.c +0 -185
  10. data/ext/protocol.h +0 -20
  11. data/ext/struct.c +0 -3
  12. data/ext/thrift_native.c +10 -11
  13. data/lib/thrift.rb +3 -0
  14. data/lib/thrift/bytes.rb +131 -0
  15. data/lib/thrift/exceptions.rb +3 -0
  16. data/lib/thrift/protocol/base_protocol.rb +96 -9
  17. data/lib/thrift/protocol/binary_protocol.rb +15 -7
  18. data/lib/thrift/protocol/compact_protocol.rb +14 -6
  19. data/lib/thrift/protocol/json_protocol.rb +766 -0
  20. data/lib/thrift/server/mongrel_http_server.rb +2 -0
  21. data/lib/thrift/server/thin_http_server.rb +91 -0
  22. data/lib/thrift/struct.rb +1 -1
  23. data/lib/thrift/struct_union.rb +2 -2
  24. data/lib/thrift/transport/base_transport.rb +22 -20
  25. data/lib/thrift/transport/buffered_transport.rb +16 -10
  26. data/lib/thrift/transport/framed_transport.rb +11 -10
  27. data/lib/thrift/transport/http_client_transport.rb +11 -6
  28. data/lib/thrift/transport/io_stream_transport.rb +1 -1
  29. data/lib/thrift/transport/memory_buffer_transport.rb +6 -6
  30. data/lib/thrift/transport/socket.rb +4 -2
  31. data/spec/ThriftSpec.thrift +52 -1
  32. data/spec/base_protocol_spec.rb +108 -51
  33. data/spec/base_transport_spec.rb +49 -50
  34. data/spec/binary_protocol_accelerated_spec.rb +9 -13
  35. data/spec/binary_protocol_spec.rb +15 -10
  36. data/spec/binary_protocol_spec_shared.rb +92 -12
  37. data/spec/bytes_spec.rb +160 -0
  38. data/spec/client_spec.rb +13 -14
  39. data/spec/compact_protocol_spec.rb +4 -5
  40. data/spec/exception_spec.rb +39 -40
  41. data/spec/gen-rb/thrift_spec_types.rb +192 -0
  42. data/spec/http_client_spec.rb +65 -9
  43. data/spec/json_protocol_spec.rb +513 -0
  44. data/spec/nonblocking_server_spec.rb +18 -20
  45. data/spec/processor_spec.rb +13 -16
  46. data/spec/serializer_spec.rb +17 -19
  47. data/spec/server_socket_spec.rb +6 -7
  48. data/spec/server_spec.rb +46 -58
  49. data/spec/socket_spec.rb +11 -11
  50. data/spec/socket_spec_shared.rb +1 -1
  51. data/spec/spec_helper.rb +13 -10
  52. data/spec/struct_nested_containers_spec.rb +191 -0
  53. data/spec/struct_spec.rb +84 -86
  54. data/spec/thin_http_server_spec.rb +140 -0
  55. data/spec/types_spec.rb +65 -66
  56. data/spec/union_spec.rb +57 -47
  57. data/spec/unix_socket_spec.rb +8 -9
  58. metadata +72 -14
  59. data/spec/mongrel_http_server_spec.rb +0 -117
data/ext/protocol.h CHANGED
@@ -1,20 +0,0 @@
1
- /*
2
- * Licensed to the Apache Software Foundation (ASF) under one
3
- * or more contributor license agreements. See the NOTICE file
4
- * distributed with this work for additional information
5
- * regarding copyright ownership. The ASF licenses this file
6
- * to you under the Apache License, Version 2.0 (the
7
- * "License"); you may not use this file except in compliance
8
- * with the License. You may obtain a copy of the License at
9
- *
10
- * http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing,
13
- * software distributed under the License is distributed on an
14
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
- * KIND, either express or implied. See the License for the
16
- * specific language governing permissions and limitations
17
- * under the License.
18
- */
19
-
20
- void Init_protocol();
data/ext/struct.c CHANGED
@@ -627,9 +627,6 @@ static VALUE rb_thrift_union_read(VALUE self, VALUE protocol) {
627
627
  rb_raise(rb_eRuntimeError, "too many fields in union!");
628
628
  }
629
629
 
630
- // read field end
631
- default_read_field_end(protocol);
632
-
633
630
  // read struct end
634
631
  default_read_struct_end(protocol);
635
632
 
data/ext/thrift_native.c CHANGED
@@ -18,15 +18,16 @@
18
18
  */
19
19
 
20
20
  #include <ruby.h>
21
+ #include <bytes.h>
21
22
  #include <struct.h>
22
23
  #include <binary_protocol_accelerated.h>
23
24
  #include <compact_protocol.h>
24
- #include <protocol.h>
25
25
  #include <memory_buffer.h>
26
26
 
27
27
  // cached classes/modules
28
28
  VALUE rb_cSet;
29
29
  VALUE thrift_module;
30
+ VALUE thrift_bytes_module;
30
31
  VALUE thrift_types_module;
31
32
 
32
33
  // TType constants
@@ -62,7 +63,6 @@ ID write_list_begin_method_id;
62
63
  ID write_list_end_method_id;
63
64
  ID write_set_begin_method_id;
64
65
  ID write_set_end_method_id;
65
- ID size_method_id;
66
66
  ID read_bool_method_id;
67
67
  ID read_byte_method_id;
68
68
  ID read_i16_method_id;
@@ -81,15 +81,15 @@ ID read_struct_end_method_id;
81
81
  ID read_field_begin_method_id;
82
82
  ID read_field_end_method_id;
83
83
  ID keys_method_id;
84
- ID entries_method_id;
85
- ID name_method_id;
86
- ID sort_method_id;
84
+ ID entries_method_id;
87
85
  ID write_field_stop_method_id;
88
86
  ID skip_method_id;
89
87
  ID write_method_id;
90
88
  ID read_all_method_id;
91
89
  ID read_into_buffer_method_id;
92
- ID native_qmark_method_id;
90
+ ID force_binary_encoding_id;
91
+ ID convert_to_utf8_byte_buffer_id;
92
+ ID convert_to_string_id;
93
93
 
94
94
  // constant ids
95
95
  ID fields_const_id;
@@ -109,6 +109,7 @@ VALUE protocol_exception_class;
109
109
  void Init_thrift_native() {
110
110
  // cached classes
111
111
  thrift_module = rb_const_get(rb_cObject, rb_intern("Thrift"));
112
+ thrift_bytes_module = rb_const_get(thrift_module, rb_intern("Bytes"));
112
113
  thrift_types_module = rb_const_get(thrift_module, rb_intern("Types"));
113
114
  rb_cSet = rb_const_get(rb_cObject, rb_intern("Set"));
114
115
  protocol_exception_class = rb_const_get(thrift_module, rb_intern("ProtocolException"));
@@ -145,7 +146,6 @@ void Init_thrift_native() {
145
146
  write_list_end_method_id = rb_intern("write_list_end");
146
147
  write_set_begin_method_id = rb_intern("write_set_begin");
147
148
  write_set_end_method_id = rb_intern("write_set_end");
148
- size_method_id = rb_intern("size");
149
149
  read_bool_method_id = rb_intern("read_bool");
150
150
  read_byte_method_id = rb_intern("read_byte");
151
151
  read_i16_method_id = rb_intern("read_i16");
@@ -165,14 +165,14 @@ void Init_thrift_native() {
165
165
  read_field_end_method_id = rb_intern("read_field_end");
166
166
  keys_method_id = rb_intern("keys");
167
167
  entries_method_id = rb_intern("entries");
168
- name_method_id = rb_intern("name");
169
- sort_method_id = rb_intern("sort");
170
168
  write_field_stop_method_id = rb_intern("write_field_stop");
171
169
  skip_method_id = rb_intern("skip");
172
170
  write_method_id = rb_intern("write");
173
171
  read_all_method_id = rb_intern("read_all");
174
172
  read_into_buffer_method_id = rb_intern("read_into_buffer");
175
- native_qmark_method_id = rb_intern("native?");
173
+ force_binary_encoding_id = rb_intern("force_binary_encoding");
174
+ convert_to_utf8_byte_buffer_id = rb_intern("convert_to_utf8_byte_buffer");
175
+ convert_to_string_id = rb_intern("convert_to_string");
176
176
 
177
177
  // constant ids
178
178
  fields_const_id = rb_intern("FIELDS");
@@ -188,7 +188,6 @@ void Init_thrift_native() {
188
188
  element_sym = ID2SYM(rb_intern("element"));
189
189
  class_sym = ID2SYM(rb_intern("class"));
190
190
 
191
- Init_protocol();
192
191
  Init_struct();
193
192
  Init_binary_protocol_accelerated();
194
193
  Init_compact_protocol();
data/lib/thrift.rb CHANGED
@@ -22,6 +22,7 @@
22
22
 
23
23
  $:.unshift File.dirname(__FILE__)
24
24
 
25
+ require 'thrift/bytes'
25
26
  require 'thrift/core_ext'
26
27
  require 'thrift/exceptions'
27
28
  require 'thrift/types'
@@ -40,6 +41,7 @@ require 'thrift/protocol/base_protocol'
40
41
  require 'thrift/protocol/binary_protocol'
41
42
  require 'thrift/protocol/binary_protocol_accelerated'
42
43
  require 'thrift/protocol/compact_protocol'
44
+ require 'thrift/protocol/json_protocol'
43
45
 
44
46
  # transport
45
47
  require 'thrift/transport/base_transport'
@@ -60,5 +62,6 @@ require 'thrift/server/nonblocking_server'
60
62
  require 'thrift/server/simple_server'
61
63
  require 'thrift/server/threaded_server'
62
64
  require 'thrift/server/thread_pool_server'
65
+ require 'thrift/server/thin_http_server'
63
66
 
64
67
  require 'thrift/thrift_native'
@@ -0,0 +1,131 @@
1
+ # encoding: ascii-8bit
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ #
20
+
21
+ module Thrift
22
+ # A collection of utilities for working with bytes and byte buffers.
23
+ module Bytes
24
+ if RUBY_VERSION >= '1.9'
25
+ # Creates and empty byte buffer (String with BINARY encoding)
26
+ #
27
+ # size - The Integer size of the buffer (default: nil) to create
28
+ #
29
+ # Returns a String with BINARY encoding, filled with null characters
30
+ # if size is greater than zero
31
+ def self.empty_byte_buffer(size = nil)
32
+ if (size && size > 0)
33
+ "\0".force_encoding(Encoding::BINARY) * size
34
+ else
35
+ ''.force_encoding(Encoding::BINARY)
36
+ end
37
+ end
38
+
39
+ # Forces the encoding of the buffer to BINARY. If the buffer
40
+ # passed is frozen, then it will be duplicated.
41
+ #
42
+ # buffer - The String to force the encoding of.
43
+ #
44
+ # Returns the String passed with an encoding of BINARY; returned
45
+ # String may be a duplicate.
46
+ def self.force_binary_encoding(buffer)
47
+ buffer = buffer.dup if buffer.frozen?
48
+ buffer.force_encoding(Encoding::BINARY)
49
+ end
50
+
51
+ # Gets the byte value of a given position in a String.
52
+ #
53
+ # string - The String to retrive the byte value from.
54
+ # index - The Integer location of the byte value to retrieve.
55
+ #
56
+ # Returns an Integer value between 0 and 255.
57
+ def self.get_string_byte(string, index)
58
+ string.getbyte(index)
59
+ end
60
+
61
+ # Sets the byte value given to a given index in a String.
62
+ #
63
+ # string - The String to set the byte value in.
64
+ # index - The Integer location to set the byte value at.
65
+ # byte - The Integer value (0 to 255) to set in the string.
66
+ #
67
+ # Returns an Integer value of the byte value to set.
68
+ def self.set_string_byte(string, index, byte)
69
+ string.setbyte(index, byte)
70
+ end
71
+
72
+ # Converts the given String to a UTF-8 byte buffer.
73
+ #
74
+ # string - The String to convert.
75
+ #
76
+ # Returns a new String with BINARY encoding, containing the UTF-8
77
+ # bytes of the original string.
78
+ def self.convert_to_utf8_byte_buffer(string)
79
+ if string.encoding != Encoding::UTF_8
80
+ # transcode to UTF-8
81
+ string = string.encode(Encoding::UTF_8)
82
+ else
83
+ # encoding is already UTF-8, but a duplicate is needed
84
+ string = string.dup
85
+ end
86
+ string.force_encoding(Encoding::BINARY)
87
+ end
88
+
89
+ # Converts the given UTF-8 byte buffer into a String
90
+ #
91
+ # utf8_buffer - A String, with BINARY encoding, containing UTF-8 bytes
92
+ #
93
+ # Returns a new String with UTF-8 encoding,
94
+ def self.convert_to_string(utf8_buffer)
95
+ # duplicate the buffer, force encoding to UTF-8
96
+ utf8_buffer.dup.force_encoding(Encoding::UTF_8)
97
+ end
98
+ else
99
+ def self.empty_byte_buffer(size = nil)
100
+ if (size && size > 0)
101
+ "\0" * size
102
+ else
103
+ ''
104
+ end
105
+ end
106
+
107
+ def self.force_binary_encoding(buffer)
108
+ buffer
109
+ end
110
+
111
+ def self.get_string_byte(string, index)
112
+ string[index]
113
+ end
114
+
115
+ def self.set_string_byte(string, index, byte)
116
+ string[index] = byte
117
+ end
118
+
119
+ def self.convert_to_utf8_byte_buffer(string)
120
+ # This assumes $KCODE is 'UTF8'/'U', which would mean the String is already a UTF-8 byte buffer
121
+ # TODO consider handling other $KCODE values and transcoding with iconv
122
+ string
123
+ end
124
+
125
+ def self.convert_to_string(utf8_buffer)
126
+ # See comment in 'convert_to_utf8_byte_buffer' for relevant assumptions.
127
+ utf8_buffer
128
+ end
129
+ end
130
+ end
131
+ end
@@ -37,6 +37,9 @@ module Thrift
37
37
  MISSING_RESULT = 5
38
38
  INTERNAL_ERROR = 6
39
39
  PROTOCOL_ERROR = 7
40
+ INVALID_TRANSFORM = 8
41
+ INVALID_PROTOCOL = 9
42
+ UNSUPPORTED_CLIENT_TYPE = 10
40
43
 
41
44
  attr_reader :type
42
45
 
@@ -114,10 +114,27 @@ module Thrift
114
114
  raise NotImplementedError
115
115
  end
116
116
 
117
+ # Writes a Thrift String. In Ruby 1.9+, the String passed will be transcoded to UTF-8.
118
+ #
119
+ # str - The String to write.
120
+ #
121
+ # Raises EncodingError if the transcoding to UTF-8 fails.
122
+ #
123
+ # Returns nothing.
117
124
  def write_string(str)
118
125
  raise NotImplementedError
119
126
  end
120
127
 
128
+ # Writes a Thrift Binary (Thrift String with no encoding). In Ruby 1.9+, the String passed
129
+ # will forced into BINARY encoding.
130
+ #
131
+ # buf - The String to write.
132
+ #
133
+ # Returns nothing.
134
+ def write_binary(buf)
135
+ raise NotImplementedError
136
+ end
137
+
121
138
  def read_message_begin
122
139
  raise NotImplementedError
123
140
  end
@@ -178,18 +195,67 @@ module Thrift
178
195
  raise NotImplementedError
179
196
  end
180
197
 
198
+ # Reads a Thrift String. In Ruby 1.9+, all Strings will be returned with an Encoding of UTF-8.
199
+ #
200
+ # Returns a String.
181
201
  def read_string
182
202
  raise NotImplementedError
183
203
  end
184
204
 
185
- def write_field(name, type, fid, value)
186
- write_field_begin(name, type, fid)
187
- write_type(type, value)
205
+ # Reads a Thrift Binary (Thrift String without encoding). In Ruby 1.9+, all Strings will be returned
206
+ # with an Encoding of BINARY.
207
+ #
208
+ # Returns a String.
209
+ def read_binary
210
+ raise NotImplementedError
211
+ end
212
+
213
+ # Writes a field based on the field information, field ID and value.
214
+ #
215
+ # field_info - A Hash containing the definition of the field:
216
+ # :name - The name of the field.
217
+ # :type - The type of the field, which must be a Thrift::Types constant.
218
+ # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
219
+ # fid - The ID of the field.
220
+ # value - The field's value to write; object type varies based on :type.
221
+ #
222
+ # Returns nothing.
223
+ def write_field(*args)
224
+ if args.size == 3
225
+ # handles the documented method signature - write_field(field_info, fid, value)
226
+ field_info = args[0]
227
+ fid = args[1]
228
+ value = args[2]
229
+ elsif args.size == 4
230
+ # handles the deprecated method signature - write_field(name, type, fid, value)
231
+ field_info = {:name => args[0], :type => args[1]}
232
+ fid = args[2]
233
+ value = args[3]
234
+ else
235
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 3)"
236
+ end
237
+
238
+ write_field_begin(field_info[:name], field_info[:type], fid)
239
+ write_type(field_info, value)
188
240
  write_field_end
189
241
  end
190
242
 
191
- def write_type(type, value)
192
- case type
243
+ # Writes a field value based on the field information.
244
+ #
245
+ # field_info - A Hash containing the definition of the field:
246
+ # :type - The Thrift::Types constant that determines how the value is written.
247
+ # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
248
+ # value - The field's value to write; object type varies based on field_info[:type].
249
+ #
250
+ # Returns nothing.
251
+ def write_type(field_info, value)
252
+ # if field_info is a Fixnum, assume it is a Thrift::Types constant
253
+ # convert it into a field_info Hash for backwards compatibility
254
+ if field_info.is_a? Fixnum
255
+ field_info = {:type => field_info}
256
+ end
257
+
258
+ case field_info[:type]
193
259
  when Types::BOOL
194
260
  write_bool(value)
195
261
  when Types::BYTE
@@ -203,7 +269,11 @@ module Thrift
203
269
  when Types::I64
204
270
  write_i64(value)
205
271
  when Types::STRING
206
- write_string(value)
272
+ if field_info[:binary]
273
+ write_binary(value)
274
+ else
275
+ write_string(value)
276
+ end
207
277
  when Types::STRUCT
208
278
  value.write(self)
209
279
  else
@@ -211,8 +281,21 @@ module Thrift
211
281
  end
212
282
  end
213
283
 
214
- def read_type(type)
215
- case type
284
+ # Reads a field value based on the field information.
285
+ #
286
+ # field_info - A Hash containing the pertinent data to write:
287
+ # :type - The Thrift::Types constant that determines how the value is written.
288
+ # :binary - A flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
289
+ #
290
+ # Returns the value read; object type varies based on field_info[:type].
291
+ def read_type(field_info)
292
+ # if field_info is a Fixnum, assume it is a Thrift::Types constant
293
+ # convert it into a field_info Hash for backwards compatibility
294
+ if field_info.is_a? Fixnum
295
+ field_info = {:type => field_info}
296
+ end
297
+
298
+ case field_info[:type]
216
299
  when Types::BOOL
217
300
  read_bool
218
301
  when Types::BYTE
@@ -226,7 +309,11 @@ module Thrift
226
309
  when Types::I64
227
310
  read_i64
228
311
  when Types::STRING
229
- read_string
312
+ if field_info[:binary]
313
+ read_binary
314
+ else
315
+ read_string
316
+ end
230
317
  else
231
318
  raise NotImplementedError
232
319
  end
@@ -32,8 +32,7 @@ module Thrift
32
32
 
33
33
  # Pre-allocated read buffer for fixed-size read methods. Needs to be at least 8 bytes long for
34
34
  # read_i64() and read_double().
35
- @rbuf = "\0" * 8
36
- @rbuf.force_encoding("BINARY") if @rbuf.respond_to?(:force_encoding)
35
+ @rbuf = Bytes.empty_byte_buffer(8)
37
36
  end
38
37
 
39
38
  def write_message_begin(name, type, seqid)
@@ -108,8 +107,13 @@ module Thrift
108
107
  end
109
108
 
110
109
  def write_string(str)
111
- write_i32(str.length)
112
- trans.write(str)
110
+ buf = Bytes.convert_to_utf8_byte_buffer(str)
111
+ write_binary(buf)
112
+ end
113
+
114
+ def write_binary(buf)
115
+ write_i32(buf.bytesize)
116
+ trans.write(buf)
113
117
  end
114
118
 
115
119
  def read_message_begin
@@ -214,9 +218,13 @@ module Thrift
214
218
  end
215
219
 
216
220
  def read_string
217
- sz = read_i32
218
- dat = trans.read_all(sz)
219
- dat
221
+ buffer = read_binary
222
+ Bytes.convert_to_string(buffer)
223
+ end
224
+
225
+ def read_binary
226
+ size = read_i32
227
+ trans.read_all(size)
220
228
  end
221
229
 
222
230
  end