protobuf 1.0.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/.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
|