protobuffy 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.travis.yml +12 -0
- data/.yardopts +5 -0
- data/CHANGES.md +261 -0
- data/CONTRIBUTING.md +16 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +14 -0
- data/README.md +58 -0
- data/Rakefile +61 -0
- data/bin/protoc-gen-ruby +17 -0
- data/bin/rpc_server +4 -0
- data/examples/bin/reverse-client-http +4 -0
- data/examples/bin/reverse-client-socket +4 -0
- data/examples/bin/reverse-client-zmq +4 -0
- data/examples/config.ru +6 -0
- data/examples/definitions/example/reverse.proto +12 -0
- data/examples/lib/example/reverse-client.rb +23 -0
- data/examples/lib/example/reverse-service.rb +9 -0
- data/examples/lib/example/reverse.pb.rb +36 -0
- data/lib/protobuf.rb +106 -0
- data/lib/protobuf/cli.rb +249 -0
- data/lib/protobuf/code_generator.rb +41 -0
- data/lib/protobuf/decoder.rb +74 -0
- data/lib/protobuf/deprecator.rb +42 -0
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +52 -0
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +249 -0
- data/lib/protobuf/encoder.rb +62 -0
- data/lib/protobuf/enum.rb +319 -0
- data/lib/protobuf/exceptions.rb +9 -0
- data/lib/protobuf/field.rb +74 -0
- data/lib/protobuf/field/base_field.rb +280 -0
- data/lib/protobuf/field/bool_field.rb +53 -0
- data/lib/protobuf/field/bytes_field.rb +81 -0
- data/lib/protobuf/field/double_field.rb +26 -0
- data/lib/protobuf/field/enum_field.rb +57 -0
- data/lib/protobuf/field/field_array.rb +86 -0
- data/lib/protobuf/field/fixed32_field.rb +25 -0
- data/lib/protobuf/field/fixed64_field.rb +29 -0
- data/lib/protobuf/field/float_field.rb +38 -0
- data/lib/protobuf/field/int32_field.rb +22 -0
- data/lib/protobuf/field/int64_field.rb +22 -0
- data/lib/protobuf/field/integer_field.rb +24 -0
- data/lib/protobuf/field/message_field.rb +66 -0
- data/lib/protobuf/field/sfixed32_field.rb +28 -0
- data/lib/protobuf/field/sfixed64_field.rb +29 -0
- data/lib/protobuf/field/signed_integer_field.rb +30 -0
- data/lib/protobuf/field/sint32_field.rb +22 -0
- data/lib/protobuf/field/sint64_field.rb +22 -0
- data/lib/protobuf/field/string_field.rb +35 -0
- data/lib/protobuf/field/uint32_field.rb +22 -0
- data/lib/protobuf/field/uint64_field.rb +22 -0
- data/lib/protobuf/field/varint_field.rb +68 -0
- data/lib/protobuf/generators/base.rb +71 -0
- data/lib/protobuf/generators/enum_generator.rb +42 -0
- data/lib/protobuf/generators/extension_generator.rb +28 -0
- data/lib/protobuf/generators/field_generator.rb +132 -0
- data/lib/protobuf/generators/file_generator.rb +140 -0
- data/lib/protobuf/generators/group_generator.rb +113 -0
- data/lib/protobuf/generators/message_generator.rb +99 -0
- data/lib/protobuf/generators/printable.rb +161 -0
- data/lib/protobuf/generators/service_generator.rb +27 -0
- data/lib/protobuf/http.rb +20 -0
- data/lib/protobuf/lifecycle.rb +46 -0
- data/lib/protobuf/logger.rb +86 -0
- data/lib/protobuf/message.rb +182 -0
- data/lib/protobuf/message/fields.rb +122 -0
- data/lib/protobuf/message/serialization.rb +84 -0
- data/lib/protobuf/optionable.rb +23 -0
- data/lib/protobuf/rpc/buffer.rb +79 -0
- data/lib/protobuf/rpc/client.rb +168 -0
- data/lib/protobuf/rpc/connector.rb +21 -0
- data/lib/protobuf/rpc/connectors/base.rb +54 -0
- data/lib/protobuf/rpc/connectors/common.rb +172 -0
- data/lib/protobuf/rpc/connectors/http.rb +90 -0
- data/lib/protobuf/rpc/connectors/socket.rb +73 -0
- data/lib/protobuf/rpc/connectors/zmq.rb +205 -0
- data/lib/protobuf/rpc/dynamic_discovery.pb.rb +47 -0
- data/lib/protobuf/rpc/env.rb +58 -0
- data/lib/protobuf/rpc/error.rb +28 -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/middleware.rb +25 -0
- data/lib/protobuf/rpc/middleware/exception_handler.rb +36 -0
- data/lib/protobuf/rpc/middleware/logger.rb +91 -0
- data/lib/protobuf/rpc/middleware/request_decoder.rb +83 -0
- data/lib/protobuf/rpc/middleware/response_encoder.rb +88 -0
- data/lib/protobuf/rpc/middleware/runner.rb +18 -0
- data/lib/protobuf/rpc/rpc.pb.rb +53 -0
- data/lib/protobuf/rpc/server.rb +39 -0
- data/lib/protobuf/rpc/servers/http/server.rb +101 -0
- data/lib/protobuf/rpc/servers/http_runner.rb +34 -0
- data/lib/protobuf/rpc/servers/socket/server.rb +113 -0
- data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
- data/lib/protobuf/rpc/servers/socket_runner.rb +34 -0
- data/lib/protobuf/rpc/servers/zmq/broker.rb +155 -0
- data/lib/protobuf/rpc/servers/zmq/server.rb +313 -0
- data/lib/protobuf/rpc/servers/zmq/util.rb +47 -0
- data/lib/protobuf/rpc/servers/zmq/worker.rb +105 -0
- data/lib/protobuf/rpc/servers/zmq_runner.rb +51 -0
- data/lib/protobuf/rpc/service.rb +179 -0
- data/lib/protobuf/rpc/service_directory.rb +245 -0
- data/lib/protobuf/rpc/service_dispatcher.rb +46 -0
- data/lib/protobuf/rpc/service_filters.rb +273 -0
- data/lib/protobuf/rpc/stat.rb +148 -0
- data/lib/protobuf/socket.rb +22 -0
- data/lib/protobuf/tasks.rb +1 -0
- data/lib/protobuf/tasks/compile.rake +61 -0
- data/lib/protobuf/version.rb +3 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/lib/protobuf/zmq.rb +21 -0
- data/proto/dynamic_discovery.proto +44 -0
- data/proto/google/protobuf/compiler/plugin.proto +147 -0
- data/proto/google/protobuf/descriptor.proto +620 -0
- data/proto/rpc.proto +62 -0
- data/protobuffy.gemspec +37 -0
- data/spec/benchmark/tasks.rb +113 -0
- data/spec/bin/protoc-gen-ruby_spec.rb +18 -0
- data/spec/data/data.bin +3 -0
- data/spec/data/types.bin +0 -0
- data/spec/encoding/all_types_spec.rb +91 -0
- data/spec/encoding/extreme_values_spec.rb +0 -0
- data/spec/functional/socket_server_spec.rb +59 -0
- data/spec/functional/zmq_server_spec.rb +103 -0
- data/spec/lib/protobuf/cli_spec.rb +267 -0
- data/spec/lib/protobuf/code_generator_spec.rb +60 -0
- data/spec/lib/protobuf/enum_spec.rb +239 -0
- data/spec/lib/protobuf/field/int32_field_spec.rb +7 -0
- data/spec/lib/protobuf/field/string_field_spec.rb +46 -0
- data/spec/lib/protobuf/field_spec.rb +194 -0
- data/spec/lib/protobuf/generators/base_spec.rb +87 -0
- data/spec/lib/protobuf/generators/enum_generator_spec.rb +68 -0
- data/spec/lib/protobuf/generators/extension_generator_spec.rb +43 -0
- data/spec/lib/protobuf/generators/field_generator_spec.rb +99 -0
- data/spec/lib/protobuf/generators/file_generator_spec.rb +29 -0
- data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
- data/spec/lib/protobuf/generators/service_generator_spec.rb +43 -0
- data/spec/lib/protobuf/lifecycle_spec.rb +89 -0
- data/spec/lib/protobuf/logger_spec.rb +136 -0
- data/spec/lib/protobuf/message_spec.rb +368 -0
- data/spec/lib/protobuf/optionable_spec.rb +46 -0
- data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
- data/spec/lib/protobuf/rpc/connector_spec.rb +26 -0
- data/spec/lib/protobuf/rpc/connectors/base_spec.rb +50 -0
- data/spec/lib/protobuf/rpc/connectors/common_spec.rb +170 -0
- data/spec/lib/protobuf/rpc/connectors/connector_spec.rb +13 -0
- data/spec/lib/protobuf/rpc/connectors/http_spec.rb +61 -0
- data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +24 -0
- data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +129 -0
- data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
- data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
- data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
- data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +75 -0
- data/spec/lib/protobuf/rpc/servers/http/server_spec.rb +104 -0
- data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +38 -0
- data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +41 -0
- data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +55 -0
- data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +35 -0
- data/spec/lib/protobuf/rpc/service_directory_spec.rb +295 -0
- data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +52 -0
- data/spec/lib/protobuf/rpc/service_filters_spec.rb +484 -0
- data/spec/lib/protobuf/rpc/service_spec.rb +161 -0
- data/spec/lib/protobuf/rpc/stat_spec.rb +151 -0
- data/spec/lib/protobuf_spec.rb +78 -0
- data/spec/spec_helper.rb +57 -0
- data/spec/support/all.rb +7 -0
- data/spec/support/packed_field.rb +22 -0
- data/spec/support/server.rb +94 -0
- data/spec/support/test/all_types.data.bin +0 -0
- data/spec/support/test/all_types.data.txt +119 -0
- data/spec/support/test/defaults.pb.rb +25 -0
- data/spec/support/test/defaults.proto +9 -0
- data/spec/support/test/enum.pb.rb +59 -0
- data/spec/support/test/enum.proto +34 -0
- data/spec/support/test/extended.pb.rb +22 -0
- data/spec/support/test/extended.proto +10 -0
- data/spec/support/test/extreme_values.data.bin +0 -0
- data/spec/support/test/google_unittest.pb.rb +543 -0
- data/spec/support/test/google_unittest.proto +713 -0
- data/spec/support/test/google_unittest_import.pb.rb +37 -0
- data/spec/support/test/google_unittest_import.proto +64 -0
- data/spec/support/test/google_unittest_import_public.pb.rb +8 -0
- data/spec/support/test/google_unittest_import_public.proto +38 -0
- data/spec/support/test/multi_field_extensions.pb.rb +56 -0
- data/spec/support/test/multi_field_extensions.proto +33 -0
- data/spec/support/test/resource.pb.rb +117 -0
- data/spec/support/test/resource.proto +94 -0
- data/spec/support/test/resource_service.rb +26 -0
- data/spec/support/test_app_file.rb +2 -0
- data/spec/support/tolerance_matcher.rb +40 -0
- metadata +367 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
class Logger < ::Logger
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_accessor :file, :level
|
8
|
+
|
9
|
+
# Stub out the log methods for Protobuf::Logger as singleton methods
|
10
|
+
[:debug, :info, :warn, :error, :fatal, :any, :add, :log].each do |m|
|
11
|
+
define_method(m) do |*params, &block|
|
12
|
+
instance && instance.__send__(m, *params, &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# One-line file/level configuration
|
18
|
+
def self.configure(options)
|
19
|
+
self.file = options.fetch(:file, false)
|
20
|
+
self.level = options.fetch(:level, false)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Use to reset the instance
|
24
|
+
def self.reset_device!
|
25
|
+
self.file = self.level = @__instance = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
# Singleton instance
|
29
|
+
def self.instance
|
30
|
+
@__instance ||= begin
|
31
|
+
log = nil
|
32
|
+
|
33
|
+
if @file && @level
|
34
|
+
log = new(self.file)
|
35
|
+
log.level = self.level
|
36
|
+
end
|
37
|
+
|
38
|
+
log
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# LogMethods module for log method including, e.g.:
|
44
|
+
#
|
45
|
+
# class MyClass
|
46
|
+
# include Protobuf::Logger::LogMethods
|
47
|
+
# ...
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# Produce a module to allow "include" in other classes to avoid
|
51
|
+
# cluttering the namespace of the including class with the other methods defined above
|
52
|
+
#
|
53
|
+
module LogMethods
|
54
|
+
[:debug, :info, :warn, :error, :fatal, :any, :add, :log].each do |m|
|
55
|
+
define_method("log_#{m}") do |*params, &block|
|
56
|
+
params.map! { |message| sign_message(message) }
|
57
|
+
::Protobuf::Logger.__send__(m, *params, &block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# When included, also extend the LogMethods module for class access.
|
62
|
+
def self.included(base)
|
63
|
+
base.extend(LogMethods)
|
64
|
+
end
|
65
|
+
|
66
|
+
# We often want to log an exception, so let's make that a core
|
67
|
+
# concern of the logger.
|
68
|
+
#
|
69
|
+
def log_exception(ex)
|
70
|
+
log_error { ex.message }
|
71
|
+
log_error { ex.backtrace[0..5].join("\n") }
|
72
|
+
log_debug { ex.backtrace.join("\n") }
|
73
|
+
end
|
74
|
+
|
75
|
+
def log_signature
|
76
|
+
@_log_signature ||= "[#{self.class == Class ? self.name : self.class.name}]"
|
77
|
+
end
|
78
|
+
|
79
|
+
def sign_message(message)
|
80
|
+
"#{log_signature} #{message}"
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'protobuf/field'
|
2
|
+
require 'protobuf/enum'
|
3
|
+
require 'protobuf/exceptions'
|
4
|
+
require 'protobuf/message/fields'
|
5
|
+
require 'protobuf/message/serialization'
|
6
|
+
|
7
|
+
module Protobuf
|
8
|
+
class Message
|
9
|
+
|
10
|
+
##
|
11
|
+
# Includes & Extends
|
12
|
+
#
|
13
|
+
|
14
|
+
extend ::Protobuf::Message::Fields
|
15
|
+
include ::Protobuf::Message::Serialization
|
16
|
+
|
17
|
+
##
|
18
|
+
# Class Methods
|
19
|
+
#
|
20
|
+
|
21
|
+
def self.to_json
|
22
|
+
name
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Constructor
|
27
|
+
#
|
28
|
+
|
29
|
+
def initialize(fields = {})
|
30
|
+
@values = {}
|
31
|
+
|
32
|
+
fields.to_hash.each_pair do |name, value|
|
33
|
+
self[name] = value unless value.nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Public Instance Methods
|
39
|
+
#
|
40
|
+
|
41
|
+
def clear!
|
42
|
+
@values.delete_if do |_, value|
|
43
|
+
if value.is_a?(::Protobuf::Field::FieldArray)
|
44
|
+
value.clear
|
45
|
+
false
|
46
|
+
else
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def clone
|
54
|
+
copy_to(super, :clone)
|
55
|
+
end
|
56
|
+
|
57
|
+
def dup
|
58
|
+
copy_to(super, :dup)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Iterate over every field, invoking the given block
|
62
|
+
#
|
63
|
+
def each_field
|
64
|
+
self.class.all_fields.each do |field|
|
65
|
+
value = __send__(field.name)
|
66
|
+
yield(field, value)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def each_field_for_serialization
|
71
|
+
self.class.all_fields.each do |field|
|
72
|
+
next unless field_must_be_serialized?(field)
|
73
|
+
|
74
|
+
value = @values[field.name]
|
75
|
+
|
76
|
+
if value.nil?
|
77
|
+
raise ::Protobuf::SerializationError, "Required field #{self.class.name}##{field.name} does not have a value."
|
78
|
+
else
|
79
|
+
yield(field, value)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def has_field?(name)
|
85
|
+
@values.has_key?(name)
|
86
|
+
end
|
87
|
+
|
88
|
+
def inspect
|
89
|
+
to_hash.inspect
|
90
|
+
end
|
91
|
+
|
92
|
+
def respond_to_has?(key)
|
93
|
+
respond_to?(key) && has_field?(key)
|
94
|
+
end
|
95
|
+
|
96
|
+
def respond_to_has_and_present?(key)
|
97
|
+
respond_to_has?(key) &&
|
98
|
+
(__send__(key).present? || [true, false].include?(__send__(key)))
|
99
|
+
end
|
100
|
+
|
101
|
+
# Return a hash-representation of the given fields for this message type.
|
102
|
+
def to_hash
|
103
|
+
result = Hash.new
|
104
|
+
|
105
|
+
@values.keys.each do |field_name|
|
106
|
+
value = __send__(field_name)
|
107
|
+
hashed_value = value.respond_to?(:to_hash_value) ? value.to_hash_value : value
|
108
|
+
result.merge!(field_name => hashed_value)
|
109
|
+
end
|
110
|
+
|
111
|
+
return result
|
112
|
+
end
|
113
|
+
|
114
|
+
def to_json(options = {})
|
115
|
+
to_hash.to_json(options)
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_proto
|
119
|
+
self
|
120
|
+
end
|
121
|
+
|
122
|
+
def ==(obj)
|
123
|
+
return false unless obj.is_a?(self.class)
|
124
|
+
each_field do |field, value|
|
125
|
+
return false unless value == obj.__send__(field.name)
|
126
|
+
end
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
130
|
+
def [](name)
|
131
|
+
if field = self.class.get_field(name, true)
|
132
|
+
__send__(field.name)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def []=(name, value)
|
137
|
+
if field = self.class.get_field(name, true)
|
138
|
+
__send__(field.setter_method_name, value)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Instance Aliases
|
144
|
+
#
|
145
|
+
alias_method :to_hash_value, :to_hash
|
146
|
+
alias_method :to_proto_hash, :to_hash
|
147
|
+
alias_method :responds_to_has?, :respond_to_has?
|
148
|
+
alias_method :respond_to_and_has?, :respond_to_has?
|
149
|
+
alias_method :responds_to_and_has?, :respond_to_has?
|
150
|
+
alias_method :respond_to_has_present?, :respond_to_has_and_present?
|
151
|
+
alias_method :respond_to_and_has_present?, :respond_to_has_and_present?
|
152
|
+
alias_method :respond_to_and_has_and_present?, :respond_to_has_and_present?
|
153
|
+
alias_method :responds_to_has_present?, :respond_to_has_and_present?
|
154
|
+
alias_method :responds_to_and_has_present?, :respond_to_has_and_present?
|
155
|
+
alias_method :responds_to_and_has_and_present?, :respond_to_has_and_present?
|
156
|
+
|
157
|
+
##
|
158
|
+
# Private Instance Methods
|
159
|
+
#
|
160
|
+
private
|
161
|
+
|
162
|
+
def copy_to(object, method)
|
163
|
+
duplicate = proc { |obj|
|
164
|
+
case obj
|
165
|
+
when Message, String then obj.__send__(method)
|
166
|
+
else obj
|
167
|
+
end
|
168
|
+
}
|
169
|
+
|
170
|
+
object.__send__(:initialize)
|
171
|
+
@values.each do |name, value|
|
172
|
+
if value.is_a?(::Protobuf::Field::FieldArray)
|
173
|
+
object.__send__(name).replace(value.map {|v| duplicate.call(v)})
|
174
|
+
else
|
175
|
+
object.__send__("#{name}=", duplicate.call(value))
|
176
|
+
end
|
177
|
+
end
|
178
|
+
object
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'protobuf/deprecator'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
class Message
|
5
|
+
module Fields
|
6
|
+
|
7
|
+
def self.extended(other)
|
8
|
+
other.extend(::Protobuf::Deprecator)
|
9
|
+
other.deprecate_class_method(:get_ext_field_by_name, :get_extension_field)
|
10
|
+
other.deprecate_class_method(:get_ext_field_by_tag, :get_extension_field)
|
11
|
+
other.deprecate_class_method(:get_field_by_name, :get_field)
|
12
|
+
other.deprecate_class_method(:get_field_by_tag, :get_field)
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Field Definition Methods
|
17
|
+
#
|
18
|
+
|
19
|
+
# Define an optional field.
|
20
|
+
#
|
21
|
+
def optional(type_class, name, tag, options = {})
|
22
|
+
define_field(:optional, type_class, name, tag, options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Define a repeated field.
|
26
|
+
#
|
27
|
+
def repeated(type_class, name, tag, options = {})
|
28
|
+
define_field(:repeated, type_class, name, tag, options)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Define a required field.
|
32
|
+
#
|
33
|
+
def required(type_class, name, tag, options = {})
|
34
|
+
define_field(:required, type_class, name, tag, options)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Define an extension range.
|
38
|
+
#
|
39
|
+
def extensions(range)
|
40
|
+
extension_ranges << range
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Field Access Methods
|
45
|
+
#
|
46
|
+
|
47
|
+
def all_fields
|
48
|
+
@all_fields ||= field_store.values.uniq
|
49
|
+
end
|
50
|
+
|
51
|
+
def extension_fields
|
52
|
+
@extension_fields ||= all_fields.select(&:extension?)
|
53
|
+
end
|
54
|
+
|
55
|
+
def extension_ranges
|
56
|
+
@extension_ranges ||= []
|
57
|
+
end
|
58
|
+
|
59
|
+
def extension_tag?(tag)
|
60
|
+
tag.respond_to?(:to_i) && get_extension_field(tag).present?
|
61
|
+
end
|
62
|
+
|
63
|
+
def field_store
|
64
|
+
@field_store ||= {}
|
65
|
+
end
|
66
|
+
|
67
|
+
def fields
|
68
|
+
@fields ||= all_fields.reject(&:extension?)
|
69
|
+
end
|
70
|
+
|
71
|
+
def field_tag?(tag, allow_extension = false)
|
72
|
+
tag.respond_to?(:to_i) && get_field(tag, allow_extension).present?
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_extension_field(name_or_tag)
|
76
|
+
name_or_tag = name_or_tag.to_sym if name_or_tag.respond_to?(:to_sym)
|
77
|
+
field = field_store[name_or_tag]
|
78
|
+
field if field.try(:extension?) { false }
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_field(name_or_tag, allow_extension = false)
|
82
|
+
name_or_tag = name_or_tag.to_sym if name_or_tag.respond_to?(:to_sym)
|
83
|
+
field = field_store[name_or_tag]
|
84
|
+
|
85
|
+
if field && (allow_extension || ! field.extension?)
|
86
|
+
field
|
87
|
+
else
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def define_field(rule, type_class, field_name, tag, options)
|
93
|
+
raise_if_tag_collision(tag, field_name)
|
94
|
+
raise_if_name_collision(field_name)
|
95
|
+
|
96
|
+
field = ::Protobuf::Field.build(self, rule, type_class, field_name, tag, options)
|
97
|
+
field_store[field_name] = field
|
98
|
+
field_store[tag] = field
|
99
|
+
|
100
|
+
class_eval(<<-RAW_GETTER, __FILE__, __LINE__ + 1)
|
101
|
+
define_method("#{field_name}!") do
|
102
|
+
@values[:#{field_name}]
|
103
|
+
end
|
104
|
+
RAW_GETTER
|
105
|
+
end
|
106
|
+
|
107
|
+
def raise_if_tag_collision(tag, field_name)
|
108
|
+
if get_field(tag, true)
|
109
|
+
raise TagCollisionError, %!Field number #{tag} has already been used in "#{name}" by field "#{field_name}".!
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def raise_if_name_collision(field_name)
|
114
|
+
if get_field(field_name, true)
|
115
|
+
raise DuplicateFieldNameError, %!Field name #{field_name} has already been used in "#{name}".!
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'protobuf/decoder'
|
3
|
+
require 'protobuf/encoder'
|
4
|
+
|
5
|
+
module Protobuf
|
6
|
+
class Message
|
7
|
+
module Serialization
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def decode(bytes)
|
11
|
+
self.new.decode(bytes)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Create a new object with the given values and return the encoded bytes.
|
15
|
+
def encode(fields = {})
|
16
|
+
self.new(fields).encode
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.included(other)
|
21
|
+
other.extend(ClassMethods)
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Instance Methods
|
26
|
+
#
|
27
|
+
|
28
|
+
# Decode the given non-stream bytes into this message.
|
29
|
+
#
|
30
|
+
def decode(bytes)
|
31
|
+
decode_from(::StringIO.new(bytes))
|
32
|
+
end
|
33
|
+
|
34
|
+
# Decode the given stream into this message.
|
35
|
+
#
|
36
|
+
def decode_from(stream)
|
37
|
+
::Protobuf::Decoder.decode_each_field(stream) do |tag, bytes|
|
38
|
+
set_field_bytes(tag, bytes)
|
39
|
+
end
|
40
|
+
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# Encode this message
|
45
|
+
#
|
46
|
+
def encode
|
47
|
+
stream = ::StringIO.new.set_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
|
48
|
+
encode_to(stream).string
|
49
|
+
end
|
50
|
+
|
51
|
+
# Encode this message to the given stream.
|
52
|
+
#
|
53
|
+
def encode_to(stream)
|
54
|
+
::Protobuf::Encoder.encode(self, stream)
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Instance Aliases
|
59
|
+
#
|
60
|
+
alias_method :parse_from_string, :decode
|
61
|
+
alias_method :deserialize, :decode
|
62
|
+
alias_method :parse_from, :decode_from
|
63
|
+
alias_method :deserialize_from, :decode_from
|
64
|
+
alias_method :to_s, :encode
|
65
|
+
alias_method :bytes, :encode
|
66
|
+
alias_method :serialize, :encode
|
67
|
+
alias_method :serialize_to_string, :encode
|
68
|
+
alias_method :serialize_to, :encode_to
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def field_must_be_serialized?(field)
|
73
|
+
field.required? || ! @values[field.name].nil?
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_field_bytes(tag, bytes)
|
77
|
+
field = self.class.get_field(tag, true)
|
78
|
+
field.set(self, bytes) if field
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|