protobuf 2.8.13 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +84 -5
- data/CONTRIBUTING.md +3 -3
- data/Rakefile +46 -7
- data/lib/protobuf/cli.rb +2 -20
- data/lib/protobuf/decoder.rb +74 -0
- data/lib/protobuf/deprecator.rb +42 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +17 -16
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +86 -85
- data/lib/protobuf/encoder.rb +62 -0
- data/lib/protobuf/enum.rb +298 -37
- data/lib/protobuf/field/base_field.rb +41 -27
- data/lib/protobuf/field/bool_field.rb +22 -4
- data/lib/protobuf/field/bytes_field.rb +36 -15
- data/lib/protobuf/field/double_field.rb +10 -3
- data/lib/protobuf/field/enum_field.rb +21 -18
- data/lib/protobuf/field/field_array.rb +26 -16
- data/lib/protobuf/field/fixed32_field.rb +10 -4
- data/lib/protobuf/field/fixed64_field.rb +10 -3
- data/lib/protobuf/field/float_field.rb +18 -5
- data/lib/protobuf/field/int32_field.rb +14 -4
- data/lib/protobuf/field/int64_field.rb +14 -4
- data/lib/protobuf/field/integer_field.rb +9 -4
- data/lib/protobuf/field/message_field.rb +16 -7
- data/lib/protobuf/field/sfixed32_field.rb +10 -3
- data/lib/protobuf/field/sfixed64_field.rb +12 -7
- data/lib/protobuf/field/signed_integer_field.rb +7 -0
- data/lib/protobuf/field/sint32_field.rb +14 -4
- data/lib/protobuf/field/sint64_field.rb +14 -4
- data/lib/protobuf/field/string_field.rb +11 -1
- data/lib/protobuf/field/uint32_field.rb +14 -4
- data/lib/protobuf/field/uint64_field.rb +14 -4
- data/lib/protobuf/field/varint_field.rb +11 -9
- data/lib/protobuf/field.rb +42 -25
- data/lib/protobuf/generators/enum_generator.rb +12 -1
- data/lib/protobuf/generators/field_generator.rb +1 -1
- data/lib/protobuf/lifecycle.rb +3 -4
- data/lib/protobuf/message/fields.rb +122 -0
- data/lib/protobuf/message/serialization.rb +84 -0
- data/lib/protobuf/message.rb +21 -221
- data/lib/protobuf/optionable.rb +23 -0
- data/lib/protobuf/rpc/client.rb +2 -4
- data/lib/protobuf/rpc/connector.rb +0 -2
- data/lib/protobuf/rpc/connectors/common.rb +2 -2
- data/lib/protobuf/rpc/dynamic_discovery.pb.rb +14 -16
- data/lib/protobuf/rpc/env.rb +58 -0
- data/lib/protobuf/rpc/error.rb +8 -5
- 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/middleware.rb +25 -0
- data/lib/protobuf/rpc/rpc.pb.rb +15 -16
- data/lib/protobuf/rpc/server.rb +14 -64
- data/lib/protobuf/rpc/servers/socket/server.rb +0 -2
- data/lib/protobuf/rpc/servers/socket/worker.rb +11 -15
- data/lib/protobuf/rpc/servers/zmq/util.rb +4 -1
- data/lib/protobuf/rpc/servers/zmq/worker.rb +5 -13
- data/lib/protobuf/rpc/servers/zmq_runner.rb +1 -1
- data/lib/protobuf/rpc/service.rb +38 -72
- data/lib/protobuf/rpc/service_dispatcher.rb +20 -108
- data/lib/protobuf/version.rb +1 -2
- data/lib/protobuf.rb +5 -13
- data/protobuf.gemspec +5 -5
- data/spec/benchmark/tasks.rb +2 -77
- data/spec/functional/zmq_server_spec.rb +13 -21
- data/spec/lib/protobuf/cli_spec.rb +5 -43
- data/spec/lib/protobuf/enum_spec.rb +194 -61
- data/spec/lib/protobuf/field_spec.rb +194 -0
- data/spec/lib/protobuf/generators/enum_generator_spec.rb +24 -1
- data/spec/lib/protobuf/generators/field_generator_spec.rb +6 -6
- data/spec/lib/protobuf/message_spec.rb +52 -70
- data/spec/lib/protobuf/optionable_spec.rb +46 -0
- data/spec/lib/protobuf/rpc/client_spec.rb +1 -93
- data/spec/lib/protobuf/rpc/connector_spec.rb +1 -7
- data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +8 -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/socket_server_spec.rb +0 -6
- data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +10 -0
- data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +30 -105
- data/spec/lib/protobuf/rpc/service_filters_spec.rb +4 -4
- data/spec/lib/protobuf/rpc/service_spec.rb +20 -24
- data/spec/lib/protobuf_spec.rb +3 -3
- data/spec/spec_helper.rb +5 -4
- data/spec/support/packed_field.rb +15 -14
- data/spec/support/server.rb +4 -21
- data/spec/support/test/defaults.pb.rb +4 -4
- data/spec/support/test/enum.pb.rb +13 -1
- data/spec/support/test/enum.proto +15 -0
- data/spec/support/test/extended.pb.rb +1 -1
- data/spec/support/test/google_unittest.pb.rb +239 -241
- data/spec/support/test/google_unittest_import.pb.rb +2 -2
- data/spec/support/test/multi_field_extensions.pb.rb +2 -2
- data/spec/support/test/resource.pb.rb +19 -18
- data/spec/support/test/resource.proto +1 -0
- data/spec/support/test/resource_service.rb +5 -0
- metadata +78 -57
- data/bin/rprotoc +0 -8
- data/lib/protobuf/enum_value.rb +0 -85
- data/lib/protobuf/evented.rb +0 -37
- data/lib/protobuf/ext/eventmachine.rb +0 -14
- data/lib/protobuf/field/extension_fields.rb +0 -32
- data/lib/protobuf/message/decoder.rb +0 -72
- data/lib/protobuf/message/message.rb +0 -1
- data/lib/protobuf/rpc/connectors/em_client.rb +0 -84
- data/lib/protobuf/rpc/connectors/eventmachine.rb +0 -87
- data/lib/protobuf/rpc/servers/evented/server.rb +0 -36
- data/lib/protobuf/rpc/servers/evented_runner.rb +0 -31
- data/spec/functional/embedded_service_spec.rb +0 -7
- data/spec/functional/evented_server_spec.rb +0 -64
- data/spec/lib/protobuf/enum_value_spec.rb +0 -29
- data/spec/lib/protobuf/rpc/servers/evented_server_spec.rb +0 -19
data/lib/protobuf/field.rb
CHANGED
@@ -19,38 +19,55 @@ require 'protobuf/field/sfixed32_field'
|
|
19
19
|
require 'protobuf/field/sfixed64_field'
|
20
20
|
require 'protobuf/field/fixed32_field'
|
21
21
|
require 'protobuf/field/fixed64_field'
|
22
|
-
require 'protobuf/field/extension_fields'
|
23
22
|
|
24
23
|
module Protobuf
|
25
24
|
module Field
|
26
|
-
|
27
|
-
|
28
|
-
::Protobuf::Field::
|
29
|
-
::Protobuf::Field::
|
30
|
-
::Protobuf::Field::
|
31
|
-
::Protobuf::Field::
|
32
|
-
::Protobuf::Field::
|
33
|
-
::Protobuf::Field::
|
34
|
-
::Protobuf::Field::
|
35
|
-
::Protobuf::Field::
|
36
|
-
::Protobuf::Field::
|
37
|
-
::Protobuf::Field::
|
38
|
-
::Protobuf::Field::
|
39
|
-
::Protobuf::Field::
|
40
|
-
::Protobuf::Field::
|
41
|
-
::Protobuf::Field::
|
42
|
-
|
25
|
+
|
26
|
+
PRIMITIVE_FIELD_MAP = {
|
27
|
+
:double => ::Protobuf::Field::DoubleField,
|
28
|
+
:float => ::Protobuf::Field::FloatField,
|
29
|
+
:int32 => ::Protobuf::Field::Int32Field,
|
30
|
+
:int64 => ::Protobuf::Field::Int64Field,
|
31
|
+
:uint32 => ::Protobuf::Field::Uint32Field,
|
32
|
+
:uint64 => ::Protobuf::Field::Uint64Field,
|
33
|
+
:sint32 => ::Protobuf::Field::Sint32Field,
|
34
|
+
:sint64 => ::Protobuf::Field::Sint64Field,
|
35
|
+
:fixed32 => ::Protobuf::Field::Fixed32Field,
|
36
|
+
:fixed64 => ::Protobuf::Field::Fixed64Field,
|
37
|
+
:sfixed32 => ::Protobuf::Field::Sfixed32Field,
|
38
|
+
:sfixed64 => ::Protobuf::Field::Sfixed64Field,
|
39
|
+
:string => ::Protobuf::Field::StringField,
|
40
|
+
:bytes => ::Protobuf::Field::BytesField,
|
41
|
+
:bool => ::Protobuf::Field::BoolField
|
42
|
+
}.freeze
|
43
43
|
|
44
44
|
def self.build(message_class, rule, type, name, tag, options = {})
|
45
|
-
field_class
|
46
|
-
|
45
|
+
field_class(type).new(message_class, rule, field_type(type), name, tag, options)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the field class for primitives,
|
49
|
+
# EnumField for types that inherit from Protobuf::Enum,
|
50
|
+
# and MessageField for types that inherit from Protobuf::Message.
|
51
|
+
#
|
52
|
+
def self.field_class(type)
|
53
|
+
if PRIMITIVE_FIELD_MAP.key?(type)
|
54
|
+
PRIMITIVE_FIELD_MAP[type]
|
55
|
+
elsif type < ::Protobuf::Enum
|
56
|
+
EnumField
|
57
|
+
elsif type < ::Protobuf::Message
|
58
|
+
MessageField
|
59
|
+
elsif type < ::Protobuf::Field::BaseField
|
60
|
+
type
|
61
|
+
else
|
62
|
+
raise ArgumentError, "Invalid field type #{type}"
|
63
|
+
end
|
47
64
|
end
|
48
65
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
66
|
+
# Returns the mapped type for primitives,
|
67
|
+
# otherwise the given type is returned.
|
68
|
+
#
|
69
|
+
def self.field_type(type)
|
70
|
+
PRIMITIVE_FIELD_MAP.fetch(type) { type }
|
54
71
|
end
|
55
72
|
|
56
73
|
end
|
@@ -4,18 +4,29 @@ module Protobuf
|
|
4
4
|
module Generators
|
5
5
|
class EnumGenerator < Base
|
6
6
|
|
7
|
+
def allow_alias?
|
8
|
+
descriptor.options.try(:allow_alias!) { false }
|
9
|
+
end
|
10
|
+
|
7
11
|
def compile
|
8
12
|
run_once(:compile) do
|
9
13
|
tags = []
|
10
14
|
|
11
15
|
print_class(descriptor.name, :enum) do
|
16
|
+
if allow_alias?
|
17
|
+
puts "set_option :allow_alias"
|
18
|
+
puts
|
19
|
+
end
|
20
|
+
|
12
21
|
descriptor.value.each do |enum_value_descriptor|
|
13
22
|
tags << enum_value_descriptor.number
|
14
23
|
puts build_value(enum_value_descriptor)
|
15
24
|
end
|
16
25
|
end
|
17
26
|
|
18
|
-
|
27
|
+
unless allow_alias?
|
28
|
+
self.class.validate_tags(fully_qualified_type_namespace, tags)
|
29
|
+
end
|
19
30
|
end
|
20
31
|
end
|
21
32
|
|
data/lib/protobuf/lifecycle.rb
CHANGED
@@ -2,10 +2,9 @@ module Protobuf
|
|
2
2
|
class Lifecycle
|
3
3
|
include ::Protobuf::Logger::LogMethods
|
4
4
|
|
5
|
-
def self.register(
|
5
|
+
def self.register(event_name, &blk)
|
6
6
|
raise "Lifecycle register must have a block" unless block_given?
|
7
|
-
|
8
|
-
event_name = normalized_event_name( event_name )
|
7
|
+
event_name = normalized_event_name(event_name)
|
9
8
|
|
10
9
|
if ::Protobuf.print_deprecation_warnings?
|
11
10
|
$stderr.puts <<-ERROR
|
@@ -32,7 +31,7 @@ module Protobuf
|
|
32
31
|
::ActiveSupport::Notifications.instrument(event_name, args)
|
33
32
|
end
|
34
33
|
|
35
|
-
def self.normalized_event_name(
|
34
|
+
def self.normalized_event_name(event_name)
|
36
35
|
return "#{event_name}".downcase
|
37
36
|
end
|
38
37
|
|
@@ -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
|
+
|
data/lib/protobuf/message.rb
CHANGED
@@ -1,147 +1,33 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
require 'set'
|
3
1
|
require 'protobuf/field'
|
4
2
|
require 'protobuf/enum'
|
5
3
|
require 'protobuf/exceptions'
|
6
|
-
require 'protobuf/message/
|
4
|
+
require 'protobuf/message/fields'
|
5
|
+
require 'protobuf/message/serialization'
|
7
6
|
|
8
7
|
module Protobuf
|
9
8
|
class Message
|
10
9
|
|
11
10
|
##
|
12
|
-
#
|
11
|
+
# Includes & Extends
|
13
12
|
#
|
14
|
-
def self.all_fields
|
15
|
-
@all_fields ||= begin
|
16
|
-
all_fields_array = []
|
17
|
-
max_fields = fields.size > extension_fields.size ? fields.size : extension_fields.size
|
18
|
-
max_fields.times do |field_number|
|
19
|
-
all_fields_array << (fields[field_number] || extension_fields[field_number])
|
20
|
-
end
|
21
|
-
all_fields_array.compact!
|
22
|
-
all_fields_array
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.decode(bytes)
|
27
|
-
self.new.decode(bytes)
|
28
|
-
end
|
29
|
-
|
30
|
-
# Define a field. Don't use this method directly.
|
31
|
-
def self.define_field(rule, type, fname, tag, options)
|
32
|
-
field_array = options[:extension] ? extension_fields : fields
|
33
|
-
field_name_hash = options[:extension] ? extension_field_name_to_tag : field_name_to_tag
|
34
|
-
|
35
|
-
previous_tag_field = get_field_by_tag(tag) || get_ext_field_by_tag(tag)
|
36
|
-
if previous_tag_field
|
37
|
-
raise TagCollisionError, %!Field number #{tag} has already been used in "#{self.name}" by field "#{fname}".!
|
38
|
-
end
|
39
|
-
|
40
|
-
previous_name_field = get_field_by_name(fname) || get_ext_field_by_name(fname)
|
41
|
-
if previous_name_field
|
42
|
-
raise DuplicateFieldNameError, %!Field name #{fname} has already been used in "#{self.name}".!
|
43
|
-
end
|
44
|
-
|
45
|
-
field_definition = ::Protobuf::Field.build(self, rule, type, fname, tag, options)
|
46
|
-
field_name_hash[fname] = tag
|
47
|
-
field_array[tag] = field_definition
|
48
|
-
|
49
|
-
define_method("#{fname}!") do
|
50
|
-
@values[fname]
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# Create a new object with the given values and return the encoded bytes.
|
55
|
-
def self.encode(values = {})
|
56
|
-
self.new(values).encode
|
57
|
-
end
|
58
|
-
|
59
|
-
# Reserve field numbers for extensions. Don't use this method directly.
|
60
|
-
def self.extensions(range)
|
61
|
-
extension_fields.add_range(range)
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.extension_field_name_to_tag
|
65
|
-
@extension_fields_by_name ||= {}
|
66
|
-
end
|
67
|
-
|
68
|
-
# An extension field object.
|
69
|
-
def self.extension_fields
|
70
|
-
@extension_fields ||= ::Protobuf::Field::ExtensionFields.new
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.extension_tag?(tag)
|
74
|
-
extension_fields.include_tag?(tag)
|
75
|
-
end
|
76
|
-
|
77
|
-
# A collection of field object.
|
78
|
-
def self.fields
|
79
|
-
@fields ||= []
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.field_name_to_tag
|
83
|
-
@field_name_to_tag ||= {}
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.get_ext_field_by_name(name)
|
87
|
-
tag = extension_field_name_to_tag[name.to_sym]
|
88
|
-
extension_fields[tag] unless tag.nil?
|
89
|
-
end
|
90
|
-
|
91
|
-
def self.get_ext_field_by_tag(tag)
|
92
|
-
extension_fields[tag]
|
93
|
-
end
|
94
|
-
|
95
|
-
# Find a field object by +name+.
|
96
|
-
def self.get_field_by_name(name)
|
97
|
-
name = name.to_sym if name.respond_to?(:to_sym)
|
98
|
-
tag = field_name_to_tag[name]
|
99
|
-
fields[tag] unless tag.nil?
|
100
|
-
end
|
101
|
-
|
102
|
-
# Find a field object by +tag+ number.
|
103
|
-
def self.get_field_by_tag(tag)
|
104
|
-
fields[tag]
|
105
|
-
rescue TypeError
|
106
|
-
tag = tag.nil? ? 'nil' : tag.to_s
|
107
|
-
raise FieldNotDefinedError.new("Tag '#{tag}' does not reference a message field for '#{self.name}'")
|
108
|
-
end
|
109
|
-
|
110
|
-
# Define a optional field. Don't use this method directly.
|
111
|
-
def self.optional(type, name, tag, options = {})
|
112
|
-
define_field(:optional, type, name, tag, options)
|
113
|
-
end
|
114
|
-
|
115
|
-
# Define a repeated field. Don't use this method directly.
|
116
|
-
def self.repeated(type, name, tag, options = {})
|
117
|
-
define_field(:repeated, type, name, tag, options)
|
118
|
-
end
|
119
13
|
|
120
|
-
|
121
|
-
|
122
|
-
define_field(:required, type, name, tag, options)
|
123
|
-
end
|
124
|
-
|
125
|
-
# Backported fix to prevent recursive to_json issues.
|
126
|
-
def self.to_json
|
127
|
-
name
|
128
|
-
end
|
14
|
+
extend ::Protobuf::Message::Fields
|
15
|
+
include ::Protobuf::Message::Serialization
|
129
16
|
|
130
17
|
##
|
131
18
|
# Constructor
|
132
19
|
#
|
133
|
-
def initialize(
|
20
|
+
def initialize(fields = {})
|
134
21
|
@values = {}
|
135
|
-
|
136
|
-
|
22
|
+
|
23
|
+
fields.to_hash.each_pair do |name, value|
|
24
|
+
self[name] = value unless value.nil?
|
25
|
+
end
|
137
26
|
end
|
138
27
|
|
139
28
|
##
|
140
29
|
# Public Instance Methods
|
141
30
|
#
|
142
|
-
def all_fields
|
143
|
-
self.class.all_fields
|
144
|
-
end
|
145
31
|
|
146
32
|
def clear!
|
147
33
|
@values.delete_if do |_, value|
|
@@ -159,95 +45,33 @@ module Protobuf
|
|
159
45
|
copy_to(super, :clone)
|
160
46
|
end
|
161
47
|
|
162
|
-
# Decode the given string bytes into this object.
|
163
|
-
def decode(string)
|
164
|
-
decode_from(::StringIO.new(string))
|
165
|
-
end
|
166
|
-
|
167
|
-
# Decode the given stream into this object.
|
168
|
-
def decode_from(stream)
|
169
|
-
Decoder.decode(stream, self)
|
170
|
-
end
|
171
|
-
|
172
48
|
def dup
|
173
49
|
copy_to(super, :dup)
|
174
50
|
end
|
175
51
|
|
176
|
-
# Iterate over
|
177
|
-
#
|
178
|
-
# # do something
|
179
|
-
# end
|
52
|
+
# Iterate over every field, invoking the given block
|
53
|
+
#
|
180
54
|
def each_field
|
181
|
-
all_fields.each do |field|
|
55
|
+
self.class.all_fields.each do |field|
|
182
56
|
value = __send__(field.name)
|
183
57
|
yield(field, value)
|
184
58
|
end
|
185
59
|
end
|
186
60
|
|
187
61
|
def each_field_for_serialization
|
188
|
-
all_fields.each do |field|
|
189
|
-
next unless
|
62
|
+
self.class.all_fields.each do |field|
|
63
|
+
next unless field_must_be_serialized?(field)
|
190
64
|
|
191
65
|
value = @values[field.name]
|
192
66
|
|
193
67
|
if value.nil?
|
194
|
-
|
195
|
-
raise ::Protobuf::SerializationError, "#{field.name} is required on #{field.message_class}"
|
68
|
+
raise ::Protobuf::SerializationError, "Required field #{self.name}##{field.name} does not have a value."
|
196
69
|
else
|
197
70
|
yield(field, value)
|
198
71
|
end
|
199
72
|
end
|
200
73
|
end
|
201
74
|
|
202
|
-
def encode
|
203
|
-
stream = ""
|
204
|
-
|
205
|
-
each_field_for_serialization do |field, value|
|
206
|
-
if field.repeated?
|
207
|
-
if field.packed?
|
208
|
-
key = (field.tag << 3) | ::Protobuf::WireType::LENGTH_DELIMITED
|
209
|
-
packed_value = value.map { |val| field.encode(val) }.join
|
210
|
-
stream << ::Protobuf::Field::VarintField.encode(key)
|
211
|
-
stream << ::Protobuf::Field::VarintField.encode(packed_value.size)
|
212
|
-
stream << packed_value
|
213
|
-
else
|
214
|
-
value.each { |val| write_pair(stream, field, val) }
|
215
|
-
end
|
216
|
-
else
|
217
|
-
write_pair(stream, field, value)
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
return stream
|
222
|
-
end
|
223
|
-
|
224
|
-
# Returns extension fields. See Message#fields method.
|
225
|
-
def extension_fields
|
226
|
-
self.class.extension_fields
|
227
|
-
end
|
228
|
-
|
229
|
-
def fields
|
230
|
-
self.class.fields
|
231
|
-
end
|
232
|
-
|
233
|
-
def get_ext_field_by_name(name) # :nodoc:
|
234
|
-
self.class.get_ext_field_by_name(name)
|
235
|
-
end
|
236
|
-
|
237
|
-
def get_ext_field_by_tag(tag) # :nodoc:
|
238
|
-
self.class.get_ext_field_by_tag(tag)
|
239
|
-
end
|
240
|
-
|
241
|
-
# Returns field object or +nil+.
|
242
|
-
def get_field_by_name(name)
|
243
|
-
self.class.get_field_by_name(name)
|
244
|
-
end
|
245
|
-
|
246
|
-
# Returns field object or +nil+.
|
247
|
-
def get_field_by_tag(tag)
|
248
|
-
self.class.get_field_by_tag(tag)
|
249
|
-
end
|
250
|
-
|
251
75
|
def has_field?(name)
|
252
76
|
@values.has_key?(name)
|
253
77
|
end
|
@@ -257,17 +81,12 @@ module Protobuf
|
|
257
81
|
end
|
258
82
|
|
259
83
|
def respond_to_has?(key)
|
260
|
-
|
84
|
+
respond_to?(key) && has_field?(key)
|
261
85
|
end
|
262
86
|
|
263
87
|
def respond_to_has_and_present?(key)
|
264
|
-
|
265
|
-
(
|
266
|
-
end
|
267
|
-
|
268
|
-
def set_field(tag, bytes)
|
269
|
-
field = (get_field_by_tag(tag) || get_ext_field_by_tag(tag))
|
270
|
-
field.set(self, bytes) if field
|
88
|
+
respond_to_has?(key) &&
|
89
|
+
(__send__(key).present? || [true, false].include?(__send__(key)))
|
271
90
|
end
|
272
91
|
|
273
92
|
# Return a hash-representation of the given fields for this message type.
|
@@ -300,13 +119,13 @@ module Protobuf
|
|
300
119
|
end
|
301
120
|
|
302
121
|
def [](name)
|
303
|
-
if field =
|
122
|
+
if field = self.class.get_field(name, true)
|
304
123
|
__send__(field.name)
|
305
124
|
end
|
306
125
|
end
|
307
126
|
|
308
127
|
def []=(name, value)
|
309
|
-
if field =
|
128
|
+
if field = self.class.get_field(name, true)
|
310
129
|
__send__(field.setter_method_name, value)
|
311
130
|
end
|
312
131
|
end
|
@@ -314,14 +133,6 @@ module Protobuf
|
|
314
133
|
##
|
315
134
|
# Instance Aliases
|
316
135
|
#
|
317
|
-
alias_method :parse_from_string, :decode
|
318
|
-
alias_method :deserialize, :decode
|
319
|
-
alias_method :parse_from, :decode_from
|
320
|
-
alias_method :deserialize_from, :decode_from
|
321
|
-
alias_method :to_s, :encode
|
322
|
-
alias_method :bytes, :encode
|
323
|
-
alias_method :serialize, :encode
|
324
|
-
alias_method :serialize_to_string, :encode
|
325
136
|
alias_method :to_hash_value, :to_hash
|
326
137
|
alias_method :to_proto_hash, :to_hash
|
327
138
|
alias_method :responds_to_has?, :respond_to_has?
|
@@ -358,16 +169,5 @@ module Protobuf
|
|
358
169
|
object
|
359
170
|
end
|
360
171
|
|
361
|
-
def __field_must_be_serialized__?(field)
|
362
|
-
field.required? || !@values[field.name].nil?
|
363
|
-
end
|
364
|
-
|
365
|
-
# Encode key and value, and write to +stream+.
|
366
|
-
def write_pair(stream, field, value)
|
367
|
-
key = (field.tag << 3) | field.wire_type
|
368
|
-
stream << ::Protobuf::Field::VarintField.encode(key)
|
369
|
-
stream << field.encode(value)
|
370
|
-
end
|
371
|
-
|
372
172
|
end
|
373
173
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Optionable
|
5
|
+
extend ::ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def get_option(name)
|
9
|
+
@_optionable_options.try(:[], name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_option(name, value = true)
|
13
|
+
@_optionable_options ||= {}
|
14
|
+
@_optionable_options[name] = value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_option(name)
|
19
|
+
self.class.get_option(name)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|