protobuf 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +28 -0
- data/README.md +216 -0
- data/Rakefile +1 -0
- data/bin/rpc_server +117 -0
- data/bin/rprotoc +46 -0
- data/examples/addressbook.pb.rb +55 -0
- data/examples/addressbook.proto +24 -0
- data/examples/reading_a_message.rb +32 -0
- data/examples/writing_a_message.rb +46 -0
- data/lib/protobuf.rb +6 -0
- data/lib/protobuf/common/exceptions.rb +11 -0
- data/lib/protobuf/common/logger.rb +64 -0
- data/lib/protobuf/common/util.rb +59 -0
- data/lib/protobuf/common/wire_type.rb +10 -0
- data/lib/protobuf/compiler/compiler.rb +52 -0
- data/lib/protobuf/compiler/nodes.rb +323 -0
- data/lib/protobuf/compiler/proto.y +216 -0
- data/lib/protobuf/compiler/proto2.ebnf +79 -0
- data/lib/protobuf/compiler/proto_parser.rb +1425 -0
- data/lib/protobuf/compiler/template/rpc_bin.erb +4 -0
- data/lib/protobuf/compiler/template/rpc_client.erb +18 -0
- data/lib/protobuf/compiler/template/rpc_service.erb +25 -0
- data/lib/protobuf/compiler/template/rpc_service_implementation.erb +42 -0
- data/lib/protobuf/compiler/visitors.rb +302 -0
- data/lib/protobuf/descriptor/descriptor.proto +286 -0
- data/lib/protobuf/descriptor/descriptor.rb +55 -0
- data/lib/protobuf/descriptor/descriptor_builder.rb +143 -0
- data/lib/protobuf/descriptor/descriptor_proto.rb +138 -0
- data/lib/protobuf/descriptor/enum_descriptor.rb +33 -0
- data/lib/protobuf/descriptor/field_descriptor.rb +49 -0
- data/lib/protobuf/descriptor/file_descriptor.rb +37 -0
- data/lib/protobuf/message/decoder.rb +83 -0
- data/lib/protobuf/message/encoder.rb +46 -0
- data/lib/protobuf/message/enum.rb +62 -0
- data/lib/protobuf/message/extend.rb +8 -0
- data/lib/protobuf/message/field.rb +701 -0
- data/lib/protobuf/message/message.rb +402 -0
- data/lib/protobuf/message/protoable.rb +38 -0
- data/lib/protobuf/rpc/buffer.rb +74 -0
- data/lib/protobuf/rpc/client.rb +268 -0
- data/lib/protobuf/rpc/client_connection.rb +225 -0
- data/lib/protobuf/rpc/error.rb +34 -0
- data/lib/protobuf/rpc/error/client_error.rb +31 -0
- data/lib/protobuf/rpc/error/server_error.rb +43 -0
- data/lib/protobuf/rpc/rpc.pb.rb +107 -0
- data/lib/protobuf/rpc/server.rb +183 -0
- data/lib/protobuf/rpc/service.rb +244 -0
- data/lib/protobuf/rpc/stat.rb +70 -0
- data/lib/protobuf/version.rb +3 -0
- data/proto/rpc.proto +73 -0
- data/protobuf.gemspec +25 -0
- data/script/mk_parser +2 -0
- data/spec/functional/embedded_service_spec.rb +7 -0
- data/spec/proto/test.pb.rb +31 -0
- data/spec/proto/test.proto +31 -0
- data/spec/proto/test_service.rb +30 -0
- data/spec/proto/test_service_impl.rb +17 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/unit/client_spec.rb +128 -0
- data/spec/unit/common/logger_spec.rb +121 -0
- data/spec/unit/enum_spec.rb +13 -0
- data/spec/unit/message_spec.rb +67 -0
- data/spec/unit/server_spec.rb +27 -0
- data/spec/unit/service_spec.rb +75 -0
- data/test/check_unbuild.rb +30 -0
- data/test/data/data.bin +3 -0
- data/test/data/data_source.py +14 -0
- data/test/data/types.bin +0 -0
- data/test/data/types_source.py +22 -0
- data/test/data/unk.png +0 -0
- data/test/proto/addressbook.pb.rb +66 -0
- data/test/proto/addressbook.proto +33 -0
- data/test/proto/addressbook_base.pb.rb +58 -0
- data/test/proto/addressbook_base.proto +26 -0
- data/test/proto/addressbook_ext.pb.rb +20 -0
- data/test/proto/addressbook_ext.proto +6 -0
- data/test/proto/collision.pb.rb +17 -0
- data/test/proto/collision.proto +5 -0
- data/test/proto/ext_collision.pb.rb +24 -0
- data/test/proto/ext_collision.proto +8 -0
- data/test/proto/ext_range.pb.rb +22 -0
- data/test/proto/ext_range.proto +7 -0
- data/test/proto/float_default.proto +10 -0
- data/test/proto/lowercase.pb.rb +30 -0
- data/test/proto/lowercase.proto +9 -0
- data/test/proto/merge.pb.rb +39 -0
- data/test/proto/merge.proto +15 -0
- data/test/proto/nested.pb.rb +30 -0
- data/test/proto/nested.proto +9 -0
- data/test/proto/optional_field.pb.rb +35 -0
- data/test/proto/optional_field.proto +12 -0
- data/test/proto/packed.pb.rb +22 -0
- data/test/proto/packed.proto +6 -0
- data/test/proto/rpc.proto +6 -0
- data/test/proto/types.pb.rb +84 -0
- data/test/proto/types.proto +37 -0
- data/test/test_addressbook.rb +56 -0
- data/test/test_compiler.rb +325 -0
- data/test/test_descriptor.rb +122 -0
- data/test/test_enum_value.rb +41 -0
- data/test/test_extension.rb +36 -0
- data/test/test_lowercase.rb +11 -0
- data/test/test_message.rb +128 -0
- data/test/test_optional_field.rb +103 -0
- data/test/test_packed_field.rb +40 -0
- data/test/test_parse.rb +15 -0
- data/test/test_repeated_types.rb +132 -0
- data/test/test_serialize.rb +61 -0
- data/test/test_standard_message.rb +96 -0
- data/test/test_types.rb +226 -0
- metadata +261 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'protobuf/common/wire_type'
|
2
|
+
require 'protobuf/common/exceptions'
|
3
|
+
|
4
|
+
module Protobuf
|
5
|
+
|
6
|
+
module Decoder
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# Read bytes from +stream+ and pass to +message+ object.
|
11
|
+
def decode(stream, message)
|
12
|
+
until stream.eof?
|
13
|
+
tag, wire_type = read_key(stream)
|
14
|
+
bytes =
|
15
|
+
case wire_type
|
16
|
+
when WireType::VARINT
|
17
|
+
read_varint(stream)
|
18
|
+
when WireType::FIXED64
|
19
|
+
read_fixed64(stream)
|
20
|
+
when WireType::LENGTH_DELIMITED
|
21
|
+
read_length_delimited(stream)
|
22
|
+
when WireType::START_GROUP
|
23
|
+
read_start_group(stream)
|
24
|
+
when WireType::END_GROUP
|
25
|
+
read_end_group(stream)
|
26
|
+
when WireType::FIXED32
|
27
|
+
read_fixed32(stream)
|
28
|
+
else
|
29
|
+
raise InvalidWireType, wire_type
|
30
|
+
end
|
31
|
+
message.set_field(tag, bytes)
|
32
|
+
end
|
33
|
+
message
|
34
|
+
end
|
35
|
+
|
36
|
+
# Read key pair (tag and wire-type) from +stream+.
|
37
|
+
def read_key(stream)
|
38
|
+
bits = read_varint(stream)
|
39
|
+
wire_type = bits & 0x07
|
40
|
+
tag = bits >> 3
|
41
|
+
[tag, wire_type]
|
42
|
+
end
|
43
|
+
|
44
|
+
# Read varint integer value from +stream+.
|
45
|
+
def read_varint(stream)
|
46
|
+
read_method = stream.respond_to?(:readbyte) ? :readbyte : :readchar
|
47
|
+
value = index = 0
|
48
|
+
begin
|
49
|
+
byte = stream.__send__(read_method)
|
50
|
+
value |= (byte & 0x7f) << (7 * index)
|
51
|
+
index += 1
|
52
|
+
end while (byte & 0x80).nonzero?
|
53
|
+
value
|
54
|
+
end
|
55
|
+
|
56
|
+
# Read 32-bit string value from +stream+.
|
57
|
+
def read_fixed32(stream)
|
58
|
+
stream.read(4)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Read 64-bit string value from +stream+.
|
62
|
+
def read_fixed64(stream)
|
63
|
+
stream.read(8)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Read length-delimited string value from +stream+.
|
67
|
+
def read_length_delimited(stream)
|
68
|
+
value_length = read_varint(stream)
|
69
|
+
stream.read(value_length)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Not implemented.
|
73
|
+
def read_start_group(stream)
|
74
|
+
raise NotImplementedError, 'Group is deprecated.'
|
75
|
+
end
|
76
|
+
|
77
|
+
# Not implemented.
|
78
|
+
def read_end_group(stream)
|
79
|
+
raise NotImplementedError, 'Group is deprecated.'
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'protobuf/common/wire_type'
|
2
|
+
require 'protobuf/common/exceptions'
|
3
|
+
|
4
|
+
module Protobuf
|
5
|
+
|
6
|
+
module Encoder
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# Encode +message+ and write to +stream+.
|
11
|
+
def encode(stream, message)
|
12
|
+
# FIXME make this not as ghetto
|
13
|
+
raise NotInitializedError, "Message %s is not initialized (one or more fields is improperly set): %s" % [message.class.name, JSON.parse(message.to_json)] unless message.initialized?
|
14
|
+
|
15
|
+
message.each_field do |field, value|
|
16
|
+
next unless message.has_field?(field.name)
|
17
|
+
|
18
|
+
if field.repeated?
|
19
|
+
if field.packed?
|
20
|
+
key = (field.tag << 3) | WireType::LENGTH_DELIMITED
|
21
|
+
packed_value = value.map {|val| field.encode(val) }.join
|
22
|
+
stream.write(Field::VarintField.encode(key))
|
23
|
+
stream.write(Field::VarintField.encode(packed_value.size))
|
24
|
+
stream.write(packed_value)
|
25
|
+
else
|
26
|
+
value.each do |val|
|
27
|
+
write_pair(stream, field, val)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
else
|
31
|
+
write_pair(stream, field, value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Encode key and value, and write to +stream+.
|
37
|
+
def write_pair(stream, field, value)
|
38
|
+
key = (field.tag << 3) | field.wire_type
|
39
|
+
key_bytes = Field::VarintField.encode(key)
|
40
|
+
stream.write(key_bytes)
|
41
|
+
bytes = field.encode(value)
|
42
|
+
stream.write(bytes)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'protobuf/descriptor/enum_descriptor'
|
3
|
+
require 'protobuf/message/protoable'
|
4
|
+
|
5
|
+
module Protobuf
|
6
|
+
class Enum
|
7
|
+
class <<self
|
8
|
+
include Protoable
|
9
|
+
|
10
|
+
attr_reader :values
|
11
|
+
|
12
|
+
def name_by_value(value)
|
13
|
+
if not defined?(@values)
|
14
|
+
constants.find {|c| const_get(c) == value} # for compatibility
|
15
|
+
else
|
16
|
+
@values_index ||= @values.inject({}) {|hash, (n, v)| hash[v.value] = n; hash }
|
17
|
+
@values_index[value]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
alias get_name_by_tag name_by_value
|
22
|
+
|
23
|
+
def valid_tag?(tag)
|
24
|
+
!! name_by_value(tag)
|
25
|
+
end
|
26
|
+
|
27
|
+
def descriptor
|
28
|
+
@descriptor ||= Descriptor::EnumDescriptor.new(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def define(name, value)
|
34
|
+
enum_value = EnumValue.new(self, name, value)
|
35
|
+
const_set(name, enum_value)
|
36
|
+
@values ||= {}
|
37
|
+
@values[name] = enum_value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class EnumValue < SimpleDelegator
|
43
|
+
|
44
|
+
attr_reader :parent_class, :name, :value
|
45
|
+
|
46
|
+
def initialize(parent_class, name, value)
|
47
|
+
@parent_class = parent_class
|
48
|
+
@name = name
|
49
|
+
@value = value
|
50
|
+
super(@value)
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
@name.to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
def inspect
|
58
|
+
"\#<#{self.class} #{@parent_class}::#{@name}=#{@value}>"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,701 @@
|
|
1
|
+
require 'protobuf/common/util'
|
2
|
+
require 'protobuf/common/wire_type'
|
3
|
+
require 'protobuf/descriptor/field_descriptor'
|
4
|
+
|
5
|
+
module Protobuf
|
6
|
+
module Field
|
7
|
+
|
8
|
+
PREDEFINED_TYPES = [
|
9
|
+
:double, :float,
|
10
|
+
:int32, :int64,
|
11
|
+
:uint32, :uint64,
|
12
|
+
:sint32, :sint64,
|
13
|
+
:fixed32, :fixed64,
|
14
|
+
:sfixed32, :sfixed64,
|
15
|
+
:string, :bytes,
|
16
|
+
:bool,
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
def self.build(message_class, rule, type, name, tag, options={})
|
20
|
+
field_class = \
|
21
|
+
if PREDEFINED_TYPES.include?(type)
|
22
|
+
const_get("#{type.to_s.capitalize}Field")
|
23
|
+
else
|
24
|
+
FieldProxy
|
25
|
+
end
|
26
|
+
field_class.new(message_class, rule, type, name, tag, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
class BaseField
|
30
|
+
|
31
|
+
def self.descriptor
|
32
|
+
@descriptor ||= Descriptor::FieldDescriptor.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.default
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :message_class, :rule, :type, :name, :tag, :default
|
40
|
+
attr_reader :default_value
|
41
|
+
|
42
|
+
def descriptor
|
43
|
+
@descriptor ||= Descriptor::FieldDescriptor.new(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(message_class, rule, type, name, tag, options)
|
47
|
+
@message_class, @rule, @type, @name, @tag = \
|
48
|
+
message_class, rule, type, name, tag
|
49
|
+
|
50
|
+
@default = options.delete(:default)
|
51
|
+
@extension = options.delete(:extension)
|
52
|
+
@packed = repeated? && options.delete(:packed)
|
53
|
+
unless options.empty?
|
54
|
+
warn "WARNING: Invalid options: #{options.inspect} (in #{@message_class.name.split('::').last}.#{@name})"
|
55
|
+
end
|
56
|
+
if packed? && ! [WireType::VARINT, WireType::FIXED32, WireType::FIXED64].include?(wire_type)
|
57
|
+
raise "Can't use packed encoding for `#{@type}' type"
|
58
|
+
end
|
59
|
+
|
60
|
+
@default_value = \
|
61
|
+
case @rule
|
62
|
+
when :repeated
|
63
|
+
FieldArray.new(self).freeze
|
64
|
+
when :required
|
65
|
+
nil
|
66
|
+
when :optional
|
67
|
+
typed_default_value
|
68
|
+
end
|
69
|
+
|
70
|
+
define_accessor
|
71
|
+
end
|
72
|
+
|
73
|
+
def ready?
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
def initialized?(message_instance)
|
78
|
+
value = message_instance.__send__(@name)
|
79
|
+
case @rule
|
80
|
+
when :required
|
81
|
+
! value.nil? && (! kind_of?(MessageField) || value.initialized?)
|
82
|
+
when :repeated
|
83
|
+
value.all? {|msg| ! kind_of?(MessageField) || msg.initialized? }
|
84
|
+
when :optional
|
85
|
+
value.nil? || ! kind_of?(MessageField) || value.initialized?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Decode +bytes+ and pass to +message_instance+.
|
90
|
+
def set(message_instance, bytes)
|
91
|
+
if packed?
|
92
|
+
array = message_instance.__send__(@name)
|
93
|
+
method = \
|
94
|
+
case wire_type
|
95
|
+
when WireType::FIXED32 then :read_fixed32
|
96
|
+
when WireType::FIXED64 then :read_fixed64
|
97
|
+
when WireType::VARINT then :read_varint
|
98
|
+
end
|
99
|
+
stream = StringIO.new(bytes)
|
100
|
+
until stream.eof?
|
101
|
+
array << decode(Decoder.__send__(method, stream))
|
102
|
+
end
|
103
|
+
else
|
104
|
+
value = decode(bytes)
|
105
|
+
if repeated?
|
106
|
+
message_instance.__send__(@name) << value
|
107
|
+
else
|
108
|
+
message_instance.__send__("#{@name}=", value)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Decode +bytes+ and return a field value.
|
114
|
+
def decode(bytes)
|
115
|
+
raise NotImplementedError, "#{self.class.name}\#decode"
|
116
|
+
end
|
117
|
+
|
118
|
+
# Encode +value+ and return a byte string.
|
119
|
+
def encode(value)
|
120
|
+
raise NotImplementedError, "#{self.class.name}\#encode"
|
121
|
+
end
|
122
|
+
|
123
|
+
# Merge +value+ with +message_instance+.
|
124
|
+
def merge(message_instance, value)
|
125
|
+
if repeated?
|
126
|
+
merge_array(message_instance, value)
|
127
|
+
else
|
128
|
+
merge_value(message_instance, value)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Is this a repeated field?
|
133
|
+
def repeated?
|
134
|
+
@rule == :repeated
|
135
|
+
end
|
136
|
+
|
137
|
+
# Is this a required field?
|
138
|
+
def required?
|
139
|
+
@rule == :required
|
140
|
+
end
|
141
|
+
|
142
|
+
# Is this a optional field?
|
143
|
+
def optional?
|
144
|
+
@rule == :optional
|
145
|
+
end
|
146
|
+
|
147
|
+
# Is this a packed repeated field?
|
148
|
+
def packed?
|
149
|
+
!!@packed
|
150
|
+
end
|
151
|
+
|
152
|
+
# Upper limit for this field.
|
153
|
+
def max
|
154
|
+
self.class.max
|
155
|
+
end
|
156
|
+
|
157
|
+
# Lower limit for this field.
|
158
|
+
def min
|
159
|
+
self.class.min
|
160
|
+
end
|
161
|
+
|
162
|
+
# Is a +value+ acceptable for this field?
|
163
|
+
def acceptable?(value)
|
164
|
+
true
|
165
|
+
end
|
166
|
+
|
167
|
+
def to_s
|
168
|
+
"#{@rule} #{@type} #{@name} = #{@tag} #{@default ? "[default=#{@default.inspect}]" : ''}"
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
def define_accessor
|
174
|
+
define_getter
|
175
|
+
if repeated?
|
176
|
+
define_array_setter
|
177
|
+
else
|
178
|
+
define_setter
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def define_getter
|
183
|
+
field = self
|
184
|
+
@message_class.class_eval do
|
185
|
+
define_method(field.name) do
|
186
|
+
if @values.has_key?(field.name)
|
187
|
+
@values[field.name]
|
188
|
+
else
|
189
|
+
field.default_value
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def define_setter
|
196
|
+
field = self
|
197
|
+
@message_class.class_eval do
|
198
|
+
define_method("#{field.name}=") do |val|
|
199
|
+
if val.nil?
|
200
|
+
@values.delete(field.name)
|
201
|
+
elsif field.acceptable?(val)
|
202
|
+
@values[field.name] = val
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def define_array_setter
|
209
|
+
field = self
|
210
|
+
@message_class.class_eval do
|
211
|
+
define_method("#{field.name}=") do |val|
|
212
|
+
@values[field.name].replace(val)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def merge_array(message_instance, value)
|
218
|
+
message_instance.__send__(@name).concat(value)
|
219
|
+
end
|
220
|
+
|
221
|
+
def merge_value(message_instance, value)
|
222
|
+
message_instance.__send__("#{@name}=", value)
|
223
|
+
end
|
224
|
+
|
225
|
+
def typed_default_value
|
226
|
+
if @default.nil?
|
227
|
+
self.class.default
|
228
|
+
else
|
229
|
+
@default
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
end # BaseField
|
234
|
+
|
235
|
+
|
236
|
+
class FieldProxy
|
237
|
+
|
238
|
+
def initialize(message_class, rule, type, name, tag, options)
|
239
|
+
@message_class, @rule, @type, @name, @tag, @options =
|
240
|
+
message_class, rule, type, name, tag, options
|
241
|
+
end
|
242
|
+
|
243
|
+
def ready?
|
244
|
+
false
|
245
|
+
end
|
246
|
+
|
247
|
+
def setup
|
248
|
+
type = typename_to_class(@message_class, @type)
|
249
|
+
field_class = \
|
250
|
+
if type < Enum
|
251
|
+
EnumField
|
252
|
+
elsif type < Message
|
253
|
+
MessageField
|
254
|
+
else
|
255
|
+
raise TypeError, type.inspect
|
256
|
+
end
|
257
|
+
field_class.new(@message_class, @rule, type, @name, @tag, @options)
|
258
|
+
end
|
259
|
+
|
260
|
+
private
|
261
|
+
|
262
|
+
def typename_to_class(message_class, type)
|
263
|
+
names = type.to_s.split('::').map {|s| Util.camelize(s) }
|
264
|
+
outer = message_class.to_s.split('::')
|
265
|
+
args = (Object.method(:const_defined?).arity == 1) ? [] : [false]
|
266
|
+
while
|
267
|
+
mod = outer.empty? ? Object : eval(outer.join('::'))
|
268
|
+
mod = names.inject(mod) {|m, s|
|
269
|
+
m && m.const_defined?(s, *args) && m.const_get(s)
|
270
|
+
}
|
271
|
+
break if mod
|
272
|
+
raise NameError.new("type not found: #{type}", type) if outer.empty?
|
273
|
+
outer.pop
|
274
|
+
end
|
275
|
+
mod
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
class FieldArray < Array
|
281
|
+
|
282
|
+
def initialize(field)
|
283
|
+
@field = field
|
284
|
+
end
|
285
|
+
|
286
|
+
def []=(nth, val)
|
287
|
+
super(nth, normalize(val))
|
288
|
+
end
|
289
|
+
|
290
|
+
def <<(val)
|
291
|
+
super(normalize(val))
|
292
|
+
end
|
293
|
+
|
294
|
+
def push(val)
|
295
|
+
super(normalize(val))
|
296
|
+
end
|
297
|
+
|
298
|
+
def unshift(val)
|
299
|
+
super(normalize(val))
|
300
|
+
end
|
301
|
+
|
302
|
+
def replace(val)
|
303
|
+
raise TypeError unless val.is_a?(Array)
|
304
|
+
val = val.map {|v| normalize(v)}
|
305
|
+
super(val)
|
306
|
+
end
|
307
|
+
|
308
|
+
def to_s
|
309
|
+
"[#{@field.name}]"
|
310
|
+
end
|
311
|
+
|
312
|
+
private
|
313
|
+
|
314
|
+
def normalize(val)
|
315
|
+
raise TypeError unless @field.acceptable?(val)
|
316
|
+
if @field.is_a?(MessageField) && val.is_a?(Hash)
|
317
|
+
@field.type.new(val)
|
318
|
+
else
|
319
|
+
val
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
end
|
324
|
+
|
325
|
+
# Field class for +bytes+ type.
|
326
|
+
class BytesField < BaseField
|
327
|
+
def self.default
|
328
|
+
''
|
329
|
+
end
|
330
|
+
|
331
|
+
def wire_type
|
332
|
+
WireType::LENGTH_DELIMITED
|
333
|
+
end
|
334
|
+
|
335
|
+
def acceptable?(val)
|
336
|
+
raise TypeError unless val.instance_of?(String)
|
337
|
+
true
|
338
|
+
end
|
339
|
+
|
340
|
+
def decode(bytes)
|
341
|
+
bytes.force_encoding('ASCII-8BIT') if bytes.respond_to?(:force_encoding)
|
342
|
+
bytes
|
343
|
+
end
|
344
|
+
|
345
|
+
def encode(value)
|
346
|
+
value = value.dup
|
347
|
+
value.force_encoding('ASCII-8BIT') if value.respond_to?(:force_encoding)
|
348
|
+
string_size = VarintField.encode(value.size)
|
349
|
+
string_size << value
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
class StringField < BytesField
|
354
|
+
def decode(bytes)
|
355
|
+
bytes.force_encoding('UTF-8') if bytes.respond_to?(:force_encoding)
|
356
|
+
bytes
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
class VarintField < BaseField
|
361
|
+
INT32_MAX = 2**31 - 1
|
362
|
+
INT32_MIN = -2**31
|
363
|
+
INT64_MAX = 2**63 - 1
|
364
|
+
INT64_MIN = -2**63
|
365
|
+
UINT32_MAX = 2**32 - 1
|
366
|
+
UINT64_MAX = 2**64 - 1
|
367
|
+
|
368
|
+
class <<self
|
369
|
+
def default
|
370
|
+
0
|
371
|
+
end
|
372
|
+
|
373
|
+
def decode(bytes)
|
374
|
+
value = 0
|
375
|
+
bytes.each_with_index do |byte, index|
|
376
|
+
value |= byte << (7 * index)
|
377
|
+
end
|
378
|
+
value
|
379
|
+
end
|
380
|
+
|
381
|
+
def encode(value)
|
382
|
+
raise RangeError, "#{value} is negative" if value < 0
|
383
|
+
return [value].pack('C') if value < 128
|
384
|
+
bytes = []
|
385
|
+
until value == 0
|
386
|
+
bytes << (0x80 | (value & 0x7f))
|
387
|
+
value >>= 7
|
388
|
+
end
|
389
|
+
bytes[-1] &= 0x7f
|
390
|
+
bytes.pack('C*')
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
def wire_type
|
395
|
+
WireType::VARINT
|
396
|
+
end
|
397
|
+
|
398
|
+
def decode(value)
|
399
|
+
value
|
400
|
+
end
|
401
|
+
|
402
|
+
def encode(value)
|
403
|
+
self.class.encode(value)
|
404
|
+
end
|
405
|
+
|
406
|
+
def acceptable?(val)
|
407
|
+
raise TypeError, val.class.name unless val.is_a?(Integer)
|
408
|
+
raise RangeError if val < min || max < val
|
409
|
+
true
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
# Base class for int32 and int64
|
414
|
+
class IntegerField < VarintField
|
415
|
+
def encode(value)
|
416
|
+
# original Google's library uses 64bits integer for negative value
|
417
|
+
VarintField.encode(value & 0xffff_ffff_ffff_ffff)
|
418
|
+
end
|
419
|
+
|
420
|
+
def decode(value)
|
421
|
+
value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero?
|
422
|
+
value
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
class Int32Field < IntegerField
|
427
|
+
def self.max; INT32_MAX; end
|
428
|
+
def self.min; INT32_MIN; end
|
429
|
+
end
|
430
|
+
|
431
|
+
class Int64Field < IntegerField
|
432
|
+
def self.max; INT64_MAX; end
|
433
|
+
def self.min; INT64_MIN; end
|
434
|
+
end
|
435
|
+
|
436
|
+
class Uint32Field < VarintField
|
437
|
+
def self.max; UINT32_MAX; end
|
438
|
+
def self.min; 0; end
|
439
|
+
end
|
440
|
+
|
441
|
+
class Uint64Field < VarintField
|
442
|
+
def self.max; UINT64_MAX; end
|
443
|
+
def self.min; 0; end
|
444
|
+
end
|
445
|
+
|
446
|
+
# Base class for sint32 and sint64
|
447
|
+
class SignedIntegerField < VarintField
|
448
|
+
def decode(value)
|
449
|
+
if (value & 1).zero?
|
450
|
+
value >> 1 # positive value
|
451
|
+
else
|
452
|
+
~value >> 1 # negative value
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
def encode(value)
|
457
|
+
if value >= 0
|
458
|
+
VarintField.encode(value << 1)
|
459
|
+
else
|
460
|
+
VarintField.encode(~(value << 1))
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
class Sint32Field < SignedIntegerField
|
466
|
+
def self.max; INT32_MAX; end
|
467
|
+
def self.min; INT32_MIN; end
|
468
|
+
end
|
469
|
+
|
470
|
+
class Sint64Field < SignedIntegerField
|
471
|
+
def self.max; INT64_MAX; end
|
472
|
+
def self.min; INT64_MIN; end
|
473
|
+
end
|
474
|
+
|
475
|
+
class FloatField < BaseField
|
476
|
+
def self.default; 0.0; end
|
477
|
+
def self.max; 1.0/0; end
|
478
|
+
def self.min; -1.0/0; end
|
479
|
+
|
480
|
+
def wire_type
|
481
|
+
WireType::FIXED32
|
482
|
+
end
|
483
|
+
|
484
|
+
def decode(bytes)
|
485
|
+
bytes.unpack('e').first
|
486
|
+
end
|
487
|
+
|
488
|
+
def encode(value)
|
489
|
+
[value].pack('e')
|
490
|
+
end
|
491
|
+
|
492
|
+
def acceptable?(val)
|
493
|
+
raise TypeError, val.class.name unless val.is_a?(Numeric)
|
494
|
+
raise RangeError if val < min || max < val
|
495
|
+
true
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
class DoubleField < FloatField
|
500
|
+
def wire_type
|
501
|
+
WireType::FIXED64
|
502
|
+
end
|
503
|
+
|
504
|
+
def decode(bytes)
|
505
|
+
bytes.unpack('E').first
|
506
|
+
end
|
507
|
+
|
508
|
+
def encode(value)
|
509
|
+
[value].pack('E')
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
class Fixed32Field < Uint32Field
|
514
|
+
def wire_type
|
515
|
+
WireType::FIXED32
|
516
|
+
end
|
517
|
+
|
518
|
+
def decode(bytes)
|
519
|
+
bytes.unpack('V').first
|
520
|
+
end
|
521
|
+
|
522
|
+
def encode(value)
|
523
|
+
[value].pack('V')
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
class Fixed64Field < Uint64Field
|
528
|
+
def wire_type
|
529
|
+
WireType::FIXED64
|
530
|
+
end
|
531
|
+
|
532
|
+
def decode(bytes)
|
533
|
+
# we don't use 'Q' for pack/unpack. 'Q' is machine-dependent.
|
534
|
+
values = bytes.unpack('VV')
|
535
|
+
values[0] + (values[1] << 32)
|
536
|
+
end
|
537
|
+
|
538
|
+
def encode(value)
|
539
|
+
# we don't use 'Q' for pack/unpack. 'Q' is machine-dependent.
|
540
|
+
[value & 0xffff_ffff, value >> 32].pack('VV')
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
class Sfixed32Field < Int32Field
|
545
|
+
def wire_type
|
546
|
+
WireType::FIXED32
|
547
|
+
end
|
548
|
+
|
549
|
+
def decode(bytes)
|
550
|
+
value = bytes.unpack('V').first
|
551
|
+
value -= 0x1_0000_0000 if (value & 0x8000_0000).nonzero?
|
552
|
+
value
|
553
|
+
end
|
554
|
+
|
555
|
+
def encode(value)
|
556
|
+
[value].pack('V')
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
class Sfixed64Field < Int64Field
|
561
|
+
def wire_type
|
562
|
+
WireType::FIXED64
|
563
|
+
end
|
564
|
+
|
565
|
+
def decode(bytes)
|
566
|
+
# we don't use 'Q' for pack/unpack. 'Q' is machine-dependent.
|
567
|
+
values = bytes.unpack('VV')
|
568
|
+
value = values[0] + (values[1] << 32)
|
569
|
+
value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero?
|
570
|
+
value
|
571
|
+
end
|
572
|
+
|
573
|
+
def encode(value)
|
574
|
+
# we don't use 'Q' for pack/unpack. 'Q' is machine-dependent.
|
575
|
+
[value & 0xffff_ffff, value >> 32].pack('VV')
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
class BoolField < VarintField
|
580
|
+
def self.default
|
581
|
+
false
|
582
|
+
end
|
583
|
+
|
584
|
+
def acceptable?(val)
|
585
|
+
raise TypeError unless [true, false].include?(val)
|
586
|
+
true
|
587
|
+
end
|
588
|
+
|
589
|
+
def decode(value)
|
590
|
+
value == 1
|
591
|
+
end
|
592
|
+
|
593
|
+
def encode(value)
|
594
|
+
[value ? 1 : 0].pack('C')
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
|
599
|
+
class MessageField < BaseField
|
600
|
+
def wire_type
|
601
|
+
WireType::LENGTH_DELIMITED
|
602
|
+
end
|
603
|
+
|
604
|
+
def acceptable?(val)
|
605
|
+
raise TypeError unless val.instance_of?(type) || val.instance_of?(Hash)
|
606
|
+
true
|
607
|
+
end
|
608
|
+
|
609
|
+
def decode(bytes)
|
610
|
+
message = type.new
|
611
|
+
message.parse_from_string(bytes)
|
612
|
+
message
|
613
|
+
end
|
614
|
+
|
615
|
+
def encode(value)
|
616
|
+
bytes = value.serialize_to_string
|
617
|
+
result = VarintField.encode(bytes.size)
|
618
|
+
result << bytes
|
619
|
+
end
|
620
|
+
|
621
|
+
private
|
622
|
+
|
623
|
+
def define_setter
|
624
|
+
field = self
|
625
|
+
@message_class.class_eval do
|
626
|
+
define_method("#{field.name}=") do |val|
|
627
|
+
case val
|
628
|
+
when nil
|
629
|
+
@values.delete(field.name)
|
630
|
+
when Hash
|
631
|
+
@values[field.name] = field.type.new(val)
|
632
|
+
when field.type
|
633
|
+
@values[field.name] = val
|
634
|
+
else
|
635
|
+
raise TypeError, "Expected value of type '#{field.type}', but got '#{val.class}'"
|
636
|
+
end
|
637
|
+
end
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
def merge_value(message_instance, value)
|
642
|
+
message_instance.__send__(@name).merge_from(value)
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
|
647
|
+
class EnumField < VarintField
|
648
|
+
def acceptable?(val)
|
649
|
+
case val
|
650
|
+
when Symbol
|
651
|
+
raise TypeError unless @type.const_defined?(val)
|
652
|
+
when EnumValue
|
653
|
+
raise TypeError if val.parent_class != @type
|
654
|
+
else
|
655
|
+
raise TypeError unless @type.valid_tag?(val)
|
656
|
+
end
|
657
|
+
true
|
658
|
+
end
|
659
|
+
|
660
|
+
def encode(value)
|
661
|
+
super(value.to_i)
|
662
|
+
end
|
663
|
+
|
664
|
+
private
|
665
|
+
|
666
|
+
def typed_default_value
|
667
|
+
if @default.is_a?(Symbol)
|
668
|
+
@type.const_get(@default)
|
669
|
+
else
|
670
|
+
self.class.default
|
671
|
+
end
|
672
|
+
end
|
673
|
+
|
674
|
+
def define_setter
|
675
|
+
field = self
|
676
|
+
@message_class.class_eval do
|
677
|
+
define_method("#{field.name}=") do |val|
|
678
|
+
if val.nil?
|
679
|
+
@values.delete(field.name)
|
680
|
+
else
|
681
|
+
val = \
|
682
|
+
case val
|
683
|
+
when Symbol
|
684
|
+
field.type.const_get(val) rescue nil
|
685
|
+
when Integer
|
686
|
+
field.type.const_get(field.type.name_by_value(val)) rescue nil
|
687
|
+
when EnumValue
|
688
|
+
raise TypeError, "Invalid value: #{val.inspect}" if val.parent_class != field.type
|
689
|
+
val
|
690
|
+
end
|
691
|
+
raise TypeError, "Invalid value: #{val.inspect}" unless val
|
692
|
+
|
693
|
+
@values[field.name] = val
|
694
|
+
end
|
695
|
+
end
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
end
|
700
|
+
end
|
701
|
+
end
|