thrift 0.2.0.4 → 0.4.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.
- data/CHANGELOG +1 -13
- data/Manifest +11 -23
- data/Rakefile +8 -6
- data/ext/binary_protocol_accelerated.c +4 -53
- data/ext/compact_protocol.c +3 -53
- data/ext/extconf.rb +4 -18
- data/ext/struct.c +181 -130
- data/ext/struct.h +2 -44
- data/ext/thrift_native.c +3 -3
- data/lib/thrift.rb +6 -1
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +5 -1
- data/lib/thrift/protocol/compact_protocol.rb +1 -0
- data/lib/thrift/server/nonblocking_server.rb +1 -2
- data/lib/thrift/struct.rb +46 -112
- data/lib/thrift/struct_union.rb +159 -0
- data/lib/thrift/transport/http_client_transport.rb +12 -6
- data/lib/thrift/transport/memory_buffer_transport.rb +2 -2
- data/lib/thrift/types.rb +1 -1
- data/lib/thrift/union.rb +179 -0
- data/spec/ThriftSpec.thrift +48 -0
- data/spec/binary_protocol_accelerated_spec.rb +18 -13
- data/spec/binary_protocol_spec_shared.rb +2 -2
- data/spec/compact_protocol_spec.rb +19 -3
- data/spec/http_client_spec.rb +17 -2
- data/spec/struct_spec.rb +34 -0
- data/spec/union_spec.rb +193 -0
- data/thrift.gemspec +11 -13
- metadata +36 -67
- data.tar.gz.sig +0 -2
- data/Makefile.am +0 -47
- data/benchmark/gen-rb/BenchmarkService.rb +0 -81
- data/benchmark/gen-rb/Benchmark_constants.rb +0 -11
- data/benchmark/gen-rb/Benchmark_types.rb +0 -10
- data/lib/thrift/protocol/binaryprotocol.rb +0 -213
- data/lib/thrift/protocol/binaryprotocolaccelerated.rb +0 -19
- data/lib/thrift/protocol/tbinaryprotocol.rb +0 -2
- data/lib/thrift/protocol/tprotocol.rb +0 -2
- data/lib/thrift/server/httpserver.rb +0 -44
- data/lib/thrift/server/nonblockingserver.rb +0 -278
- data/lib/thrift/server/thttpserver.rb +0 -2
- data/lib/thrift/server/tserver.rb +0 -2
- data/spec/gen-rb/NonblockingService.rb +0 -268
- data/spec/gen-rb/ThriftSpec_constants.rb +0 -11
- data/spec/gen-rb/ThriftSpec_types.rb +0 -134
- metadata.gz.sig +0 -0
data/ext/struct.h
CHANGED
@@ -17,51 +17,9 @@
|
|
17
17
|
* under the License.
|
18
18
|
*/
|
19
19
|
|
20
|
+
|
20
21
|
#include <stdbool.h>
|
21
22
|
#include <ruby.h>
|
22
23
|
|
23
|
-
typedef struct native_proto_method_table {
|
24
|
-
VALUE (*write_bool)(VALUE, VALUE);
|
25
|
-
VALUE (*write_byte)(VALUE, VALUE);
|
26
|
-
VALUE (*write_i16)(VALUE, VALUE);
|
27
|
-
VALUE (*write_i32)(VALUE, VALUE);
|
28
|
-
VALUE (*write_i64)(VALUE, VALUE);
|
29
|
-
VALUE (*write_double)(VALUE, VALUE);
|
30
|
-
VALUE (*write_string)(VALUE, VALUE);
|
31
|
-
VALUE (*write_list_begin)(VALUE, VALUE, VALUE);
|
32
|
-
VALUE (*write_list_end)(VALUE);
|
33
|
-
VALUE (*write_set_begin)(VALUE, VALUE, VALUE);
|
34
|
-
VALUE (*write_set_end)(VALUE);
|
35
|
-
VALUE (*write_map_begin)(VALUE, VALUE, VALUE, VALUE);
|
36
|
-
VALUE (*write_map_end)(VALUE);
|
37
|
-
VALUE (*write_struct_begin)(VALUE, VALUE);
|
38
|
-
VALUE (*write_struct_end)(VALUE);
|
39
|
-
VALUE (*write_field_begin)(VALUE, VALUE, VALUE, VALUE);
|
40
|
-
VALUE (*write_field_end)(VALUE);
|
41
|
-
VALUE (*write_field_stop)(VALUE);
|
42
|
-
VALUE (*write_message_begin)(VALUE, VALUE, VALUE, VALUE);
|
43
|
-
VALUE (*write_message_end)(VALUE);
|
44
|
-
|
45
|
-
VALUE (*read_message_begin)(VALUE);
|
46
|
-
VALUE (*read_message_end)(VALUE);
|
47
|
-
VALUE (*read_field_begin)(VALUE);
|
48
|
-
VALUE (*read_field_end)(VALUE);
|
49
|
-
VALUE (*read_map_begin)(VALUE);
|
50
|
-
VALUE (*read_map_end)(VALUE);
|
51
|
-
VALUE (*read_list_begin)(VALUE);
|
52
|
-
VALUE (*read_list_end)(VALUE);
|
53
|
-
VALUE (*read_set_begin)(VALUE);
|
54
|
-
VALUE (*read_set_end)(VALUE);
|
55
|
-
VALUE (*read_byte)(VALUE);
|
56
|
-
VALUE (*read_bool)(VALUE);
|
57
|
-
VALUE (*read_i16)(VALUE);
|
58
|
-
VALUE (*read_i32)(VALUE);
|
59
|
-
VALUE (*read_i64)(VALUE);
|
60
|
-
VALUE (*read_double)(VALUE);
|
61
|
-
VALUE (*read_string)(VALUE);
|
62
|
-
VALUE (*read_struct_begin)(VALUE);
|
63
|
-
VALUE (*read_struct_end)(VALUE);
|
64
|
-
|
65
|
-
} native_proto_method_table;
|
66
|
-
|
67
24
|
void Init_struct();
|
25
|
+
void Init_union();
|
data/ext/thrift_native.c
CHANGED
@@ -111,7 +111,7 @@ void Init_thrift_native() {
|
|
111
111
|
thrift_types_module = rb_const_get(thrift_module, rb_intern("Types"));
|
112
112
|
rb_cSet = rb_const_get(rb_cObject, rb_intern("Set"));
|
113
113
|
protocol_exception_class = rb_const_get(thrift_module, rb_intern("ProtocolException"));
|
114
|
-
|
114
|
+
|
115
115
|
// Init ttype constants
|
116
116
|
TTYPE_BOOL = FIX2INT(rb_const_get(thrift_types_module, rb_intern("BOOL")));
|
117
117
|
TTYPE_BYTE = FIX2INT(rb_const_get(thrift_types_module, rb_intern("BYTE")));
|
@@ -171,13 +171,13 @@ void Init_thrift_native() {
|
|
171
171
|
write_method_id = rb_intern("write");
|
172
172
|
read_all_method_id = rb_intern("read_all");
|
173
173
|
native_qmark_method_id = rb_intern("native?");
|
174
|
-
|
174
|
+
|
175
175
|
// constant ids
|
176
176
|
fields_const_id = rb_intern("FIELDS");
|
177
177
|
transport_ivar_id = rb_intern("@trans");
|
178
178
|
strict_read_ivar_id = rb_intern("@strict_read");
|
179
179
|
strict_write_ivar_id = rb_intern("@strict_write");
|
180
|
-
|
180
|
+
|
181
181
|
// cached symbols
|
182
182
|
type_sym = ID2SYM(rb_intern("type"));
|
183
183
|
name_sym = ID2SYM(rb_intern("name"));
|
data/lib/thrift.rb
CHANGED
@@ -16,6 +16,9 @@
|
|
16
16
|
# specific language governing permissions and limitations
|
17
17
|
# under the License.
|
18
18
|
#
|
19
|
+
# Contains some contributions under the Thrift Software License.
|
20
|
+
# Please see doc/old-thrift-license.txt in the Thrift distribution for
|
21
|
+
# details.
|
19
22
|
|
20
23
|
$:.unshift File.dirname(__FILE__)
|
21
24
|
|
@@ -25,6 +28,8 @@ require 'thrift/types'
|
|
25
28
|
require 'thrift/processor'
|
26
29
|
require 'thrift/client'
|
27
30
|
require 'thrift/struct'
|
31
|
+
require 'thrift/union'
|
32
|
+
require 'thrift/struct_union'
|
28
33
|
|
29
34
|
# serializer
|
30
35
|
require 'thrift/serializer/serializer'
|
@@ -56,4 +61,4 @@ require 'thrift/server/simple_server'
|
|
56
61
|
require 'thrift/server/threaded_server'
|
57
62
|
require 'thrift/server/thread_pool_server'
|
58
63
|
|
59
|
-
require 'thrift/thrift_native'
|
64
|
+
require 'thrift/thrift_native'
|
@@ -29,7 +29,11 @@ See MemoryBuffer and BufferedTransport for examples.
|
|
29
29
|
module Thrift
|
30
30
|
class BinaryProtocolAcceleratedFactory < BaseProtocolFactory
|
31
31
|
def get_protocol(trans)
|
32
|
-
BinaryProtocolAccelerated
|
32
|
+
if (defined? BinaryProtocolAccelerated)
|
33
|
+
BinaryProtocolAccelerated.new(trans)
|
34
|
+
else
|
35
|
+
BinaryProtocol.new(trans)
|
36
|
+
end
|
33
37
|
end
|
34
38
|
end
|
35
39
|
end
|
@@ -160,8 +160,7 @@ module Thrift
|
|
160
160
|
|
161
161
|
def read_connection(fd)
|
162
162
|
@buffers[fd] << fd.read(DEFAULT_BUFFER)
|
163
|
-
frame = slice_frame!(@buffers[fd])
|
164
|
-
if frame
|
163
|
+
while(frame = slice_frame!(@buffers[fd]))
|
165
164
|
@logger.debug "#{self} is processing a frame"
|
166
165
|
@worker_queue.push [:frame, fd, frame]
|
167
166
|
end
|
data/lib/thrift/struct.rb
CHANGED
@@ -65,33 +65,14 @@ module Thrift
|
|
65
65
|
end
|
66
66
|
fields_with_default_values
|
67
67
|
end
|
68
|
-
|
69
|
-
def name_to_id(name)
|
70
|
-
names_to_ids = self.class.instance_variable_get("@names_to_ids")
|
71
|
-
unless names_to_ids
|
72
|
-
names_to_ids = {}
|
73
|
-
struct_fields.each do |fid, field_def|
|
74
|
-
names_to_ids[field_def[:name]] = fid
|
75
|
-
end
|
76
|
-
self.class.instance_variable_set("@names_to_ids", names_to_ids)
|
77
|
-
end
|
78
|
-
names_to_ids[name]
|
79
|
-
end
|
80
|
-
|
81
|
-
def each_field
|
82
|
-
struct_fields.keys.sort.each do |fid|
|
83
|
-
data = struct_fields[fid]
|
84
|
-
yield fid, data
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
68
|
+
|
88
69
|
def inspect(skip_optional_nulls = true)
|
89
70
|
fields = []
|
90
71
|
each_field do |fid, field_info|
|
91
72
|
name = field_info[:name]
|
92
73
|
value = instance_variable_get("@#{name}")
|
93
74
|
unless skip_optional_nulls && field_info[:optional] && value.nil?
|
94
|
-
fields << "#{name}:#{value
|
75
|
+
fields << "#{name}:#{inspect_field(value, field_info)}"
|
95
76
|
end
|
96
77
|
end
|
97
78
|
"<#{self.class} #{fields.join(", ")}>"
|
@@ -115,7 +96,8 @@ module Thrift
|
|
115
96
|
each_field do |fid, field_info|
|
116
97
|
name = field_info[:name]
|
117
98
|
type = field_info[:type]
|
118
|
-
|
99
|
+
value = instance_variable_get("@#{name}")
|
100
|
+
unless value.nil?
|
119
101
|
if is_container? type
|
120
102
|
oprot.write_field_begin(name, type, fid)
|
121
103
|
write_container(oprot, value, field_info)
|
@@ -163,13 +145,49 @@ module Thrift
|
|
163
145
|
diffs
|
164
146
|
end
|
165
147
|
|
166
|
-
def self.field_accessor(klass,
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
148
|
+
def self.field_accessor(klass, field_info)
|
149
|
+
field_name_sym = field_info[:name].to_sym
|
150
|
+
klass.send :attr_reader, field_name_sym
|
151
|
+
klass.send :define_method, "#{field_info[:name]}=" do |value|
|
152
|
+
Thrift.check_type(value, field_info, field_info[:name]) if Thrift.type_checking
|
153
|
+
instance_variable_set("@#{field_name_sym}", value)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.generate_accessors(klass)
|
158
|
+
klass::FIELDS.values.each do |field_info|
|
159
|
+
field_accessor(klass, field_info)
|
160
|
+
qmark_isset_method(klass, field_info)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.qmark_isset_method(klass, field_info)
|
165
|
+
klass.send :define_method, "#{field_info[:name]}?" do
|
166
|
+
!self.send(field_info[:name].to_sym).nil?
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def <=>(other)
|
171
|
+
if self.class == other.class
|
172
|
+
each_field do |fid, field_info|
|
173
|
+
v1 = self.send(field_info[:name])
|
174
|
+
v1_set = !v1.nil?
|
175
|
+
v2 = other.send(field_info[:name])
|
176
|
+
v2_set = !v2.nil?
|
177
|
+
if v1_set && !v2_set
|
178
|
+
return -1
|
179
|
+
elsif !v1_set && v2_set
|
180
|
+
return 1
|
181
|
+
elsif v1_set && v2_set
|
182
|
+
cmp = v1 <=> v2
|
183
|
+
if cmp != 0
|
184
|
+
return cmp
|
185
|
+
end
|
186
|
+
end
|
172
187
|
end
|
188
|
+
0
|
189
|
+
else
|
190
|
+
self.class <=> other.class
|
173
191
|
end
|
174
192
|
end
|
175
193
|
|
@@ -210,89 +228,5 @@ module Thrift
|
|
210
228
|
iprot.skip(ftype)
|
211
229
|
end
|
212
230
|
end
|
213
|
-
|
214
|
-
def read_field(iprot, field = {})
|
215
|
-
case field[:type]
|
216
|
-
when Types::STRUCT
|
217
|
-
value = field[:class].new
|
218
|
-
value.read(iprot)
|
219
|
-
when Types::MAP
|
220
|
-
key_type, val_type, size = iprot.read_map_begin
|
221
|
-
value = {}
|
222
|
-
size.times do
|
223
|
-
k = read_field(iprot, field_info(field[:key]))
|
224
|
-
v = read_field(iprot, field_info(field[:value]))
|
225
|
-
value[k] = v
|
226
|
-
end
|
227
|
-
iprot.read_map_end
|
228
|
-
when Types::LIST
|
229
|
-
e_type, size = iprot.read_list_begin
|
230
|
-
value = Array.new(size) do |n|
|
231
|
-
read_field(iprot, field_info(field[:element]))
|
232
|
-
end
|
233
|
-
iprot.read_list_end
|
234
|
-
when Types::SET
|
235
|
-
e_type, size = iprot.read_set_begin
|
236
|
-
value = Set.new
|
237
|
-
size.times do
|
238
|
-
element = read_field(iprot, field_info(field[:element]))
|
239
|
-
value << element
|
240
|
-
end
|
241
|
-
iprot.read_set_end
|
242
|
-
else
|
243
|
-
value = iprot.read_type(field[:type])
|
244
|
-
end
|
245
|
-
value
|
246
|
-
end
|
247
|
-
|
248
|
-
def write_data(oprot, value, field)
|
249
|
-
if is_container? field[:type]
|
250
|
-
write_container(oprot, value, field)
|
251
|
-
else
|
252
|
-
oprot.write_type(field[:type], value)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
def write_container(oprot, value, field = {})
|
257
|
-
case field[:type]
|
258
|
-
when Types::MAP
|
259
|
-
oprot.write_map_begin(field[:key][:type], field[:value][:type], value.size)
|
260
|
-
value.each do |k, v|
|
261
|
-
write_data(oprot, k, field[:key])
|
262
|
-
write_data(oprot, v, field[:value])
|
263
|
-
end
|
264
|
-
oprot.write_map_end
|
265
|
-
when Types::LIST
|
266
|
-
oprot.write_list_begin(field[:element][:type], value.size)
|
267
|
-
value.each do |elem|
|
268
|
-
write_data(oprot, elem, field[:element])
|
269
|
-
end
|
270
|
-
oprot.write_list_end
|
271
|
-
when Types::SET
|
272
|
-
oprot.write_set_begin(field[:element][:type], value.size)
|
273
|
-
value.each do |v,| # the , is to preserve compatibility with the old Hash-style sets
|
274
|
-
write_data(oprot, v, field[:element])
|
275
|
-
end
|
276
|
-
oprot.write_set_end
|
277
|
-
else
|
278
|
-
raise "Not a container type: #{field[:type]}"
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
CONTAINER_TYPES = []
|
283
|
-
CONTAINER_TYPES[Types::LIST] = true
|
284
|
-
CONTAINER_TYPES[Types::MAP] = true
|
285
|
-
CONTAINER_TYPES[Types::SET] = true
|
286
|
-
def is_container?(type)
|
287
|
-
CONTAINER_TYPES[type]
|
288
|
-
end
|
289
|
-
|
290
|
-
def field_info(field)
|
291
|
-
{ :type => field[:type],
|
292
|
-
:class => field[:class],
|
293
|
-
:key => field[:key],
|
294
|
-
:value => field[:value],
|
295
|
-
:element => field[:element] }
|
296
|
-
end
|
297
231
|
end
|
298
232
|
end
|
@@ -0,0 +1,159 @@
|
|
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
|
+
require 'set'
|
20
|
+
|
21
|
+
module Thrift
|
22
|
+
module Struct_Union
|
23
|
+
def name_to_id(name)
|
24
|
+
names_to_ids = self.class.instance_variable_get("@names_to_ids")
|
25
|
+
unless names_to_ids
|
26
|
+
names_to_ids = {}
|
27
|
+
struct_fields.each do |fid, field_def|
|
28
|
+
names_to_ids[field_def[:name]] = fid
|
29
|
+
end
|
30
|
+
self.class.instance_variable_set("@names_to_ids", names_to_ids)
|
31
|
+
end
|
32
|
+
names_to_ids[name]
|
33
|
+
end
|
34
|
+
|
35
|
+
def each_field
|
36
|
+
struct_fields.keys.sort.each do |fid|
|
37
|
+
data = struct_fields[fid]
|
38
|
+
yield fid, data
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def read_field(iprot, field = {})
|
43
|
+
case field[:type]
|
44
|
+
when Types::STRUCT
|
45
|
+
value = field[:class].new
|
46
|
+
value.read(iprot)
|
47
|
+
when Types::MAP
|
48
|
+
key_type, val_type, size = iprot.read_map_begin
|
49
|
+
value = {}
|
50
|
+
size.times do
|
51
|
+
k = read_field(iprot, field_info(field[:key]))
|
52
|
+
v = read_field(iprot, field_info(field[:value]))
|
53
|
+
value[k] = v
|
54
|
+
end
|
55
|
+
iprot.read_map_end
|
56
|
+
when Types::LIST
|
57
|
+
e_type, size = iprot.read_list_begin
|
58
|
+
value = Array.new(size) do |n|
|
59
|
+
read_field(iprot, field_info(field[:element]))
|
60
|
+
end
|
61
|
+
iprot.read_list_end
|
62
|
+
when Types::SET
|
63
|
+
e_type, size = iprot.read_set_begin
|
64
|
+
value = Set.new
|
65
|
+
size.times do
|
66
|
+
element = read_field(iprot, field_info(field[:element]))
|
67
|
+
value << element
|
68
|
+
end
|
69
|
+
iprot.read_set_end
|
70
|
+
else
|
71
|
+
value = iprot.read_type(field[:type])
|
72
|
+
end
|
73
|
+
value
|
74
|
+
end
|
75
|
+
|
76
|
+
def write_data(oprot, value, field)
|
77
|
+
if is_container? field[:type]
|
78
|
+
write_container(oprot, value, field)
|
79
|
+
else
|
80
|
+
oprot.write_type(field[:type], value)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def write_container(oprot, value, field = {})
|
85
|
+
case field[:type]
|
86
|
+
when Types::MAP
|
87
|
+
oprot.write_map_begin(field[:key][:type], field[:value][:type], value.size)
|
88
|
+
value.each do |k, v|
|
89
|
+
write_data(oprot, k, field[:key])
|
90
|
+
write_data(oprot, v, field[:value])
|
91
|
+
end
|
92
|
+
oprot.write_map_end
|
93
|
+
when Types::LIST
|
94
|
+
oprot.write_list_begin(field[:element][:type], value.size)
|
95
|
+
value.each do |elem|
|
96
|
+
write_data(oprot, elem, field[:element])
|
97
|
+
end
|
98
|
+
oprot.write_list_end
|
99
|
+
when Types::SET
|
100
|
+
oprot.write_set_begin(field[:element][:type], value.size)
|
101
|
+
value.each do |v,| # the , is to preserve compatibility with the old Hash-style sets
|
102
|
+
write_data(oprot, v, field[:element])
|
103
|
+
end
|
104
|
+
oprot.write_set_end
|
105
|
+
else
|
106
|
+
raise "Not a container type: #{field[:type]}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
CONTAINER_TYPES = []
|
111
|
+
CONTAINER_TYPES[Types::LIST] = true
|
112
|
+
CONTAINER_TYPES[Types::MAP] = true
|
113
|
+
CONTAINER_TYPES[Types::SET] = true
|
114
|
+
def is_container?(type)
|
115
|
+
CONTAINER_TYPES[type]
|
116
|
+
end
|
117
|
+
|
118
|
+
def field_info(field)
|
119
|
+
{ :type => field[:type],
|
120
|
+
:class => field[:class],
|
121
|
+
:key => field[:key],
|
122
|
+
:value => field[:value],
|
123
|
+
:element => field[:element] }
|
124
|
+
end
|
125
|
+
|
126
|
+
def inspect_field(value, field_info)
|
127
|
+
if enum_class = field_info[:enum_class]
|
128
|
+
"#{enum_class.const_get(:VALUE_MAP)[value]} (#{value})"
|
129
|
+
elsif value.is_a? Hash
|
130
|
+
if field_info[:type] == Types::MAP
|
131
|
+
map_buf = []
|
132
|
+
value.each do |k, v|
|
133
|
+
map_buf << inspect_field(k, field_info[:key]) + ": " + inspect_field(v, field_info[:value])
|
134
|
+
end
|
135
|
+
"{" + map_buf.join(", ") + "}"
|
136
|
+
else
|
137
|
+
# old-style set
|
138
|
+
inspect_collection(value.keys, field_info)
|
139
|
+
end
|
140
|
+
elsif value.is_a? Array
|
141
|
+
inspect_collection(value, field_info)
|
142
|
+
elsif value.is_a? Set
|
143
|
+
inspect_collection(value, field_info)
|
144
|
+
elsif value.is_a?(String) && field_info[:binary]
|
145
|
+
value.unpack("H*").first
|
146
|
+
else
|
147
|
+
value.inspect
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def inspect_collection(collection, field_info)
|
152
|
+
buf = []
|
153
|
+
collection.each do |k|
|
154
|
+
buf << inspect_field(k, field_info[:element])
|
155
|
+
end
|
156
|
+
"[" + buf.join(", ") + "]"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|