Class: Protobuf::Message
- Inherits:
-
Object
- Object
- Protobuf::Message
- Extended by:
- Protoable
- Defined in:
- lib/protobuf/message/message.rb
Direct Known Subclasses
Google::Protobuf::DescriptorProto, Google::Protobuf::DescriptorProto::ExtensionRange, Google::Protobuf::EnumDescriptorProto, Google::Protobuf::EnumOptions, Google::Protobuf::EnumValueDescriptorProto, Google::Protobuf::EnumValueOptions, Google::Protobuf::FieldDescriptorProto, Google::Protobuf::FieldOptions, Google::Protobuf::FileDescriptorProto, Google::Protobuf::FileOptions, Google::Protobuf::MessageOptions, Google::Protobuf::MethodDescriptorProto, Google::Protobuf::MethodOptions, Google::Protobuf::ServiceDescriptorProto, Google::Protobuf::ServiceOptions, Extend
Class Method Summary collapse
-
.clear_field_cache ⇒ Object
:nodoc:.
-
.define_field(rule, type, fname, tag, options) ⇒ Object
Define a field.
- .descriptor ⇒ Object
- .extension_tag?(tag) ⇒ Boolean
-
.extensions(range) ⇒ Object
Reserve field numbers for extensions.
-
.field_dictionary ⇒ Object
:nodoc:.
-
.fields ⇒ Object
A collection of field object.
-
.get_field(tag_or_name) ⇒ Object
Find a field object by
tag_or_name. -
.get_field_by_name ⇒ Object
Find a field object by
tag_or_name. -
.get_field_by_tag ⇒ Object
Find a field object by
tag_or_name. -
.optional(type, name, tag, options = {}) ⇒ Object
Define a optional field.
-
.repeated(type, name, tag, options = {}) ⇒ Object
Define a repeated field.
-
.required(type, name, tag, options = {}) ⇒ Object
Define a required field.
-
.sorted_fields ⇒ Object
A collection of field object, which is sorted by tag number.
Instance Method Summary collapse
- #==(obj) ⇒ Object
- #[](tag_or_name) ⇒ Object
- #[]=(tag_or_name, value) ⇒ Object
- #clear! ⇒ Object
- #clone ⇒ Object
- #dup ⇒ Object
-
#each_field ⇒ Object
Iterate over a field collection.
-
#fields ⇒ Object
Returns a hash; which key is a tag number, and value is a field object.
-
#get_field(tag_or_name) ⇒ Object
Returns field object or
nil. -
#get_field_by_name(name) ⇒ Object
Returns field object or
nil. -
#get_field_by_tag(tag) ⇒ Object
Returns field object or
nil. - #has_field?(tag_or_name) ⇒ Boolean
-
#initialize(values = {}) ⇒ Message
constructor
A new instance of Message.
- #initialized? ⇒ Boolean
- #inspect(indent = 0) ⇒ Object
- #merge_from(message) ⇒ Object
- #parse_from(stream) ⇒ Object
- #parse_from_file(filename) ⇒ Object
- #parse_from_string(string) ⇒ Object
- #serialize_to(stream) ⇒ Object
- #serialize_to_file(filename) ⇒ Object
- #serialize_to_string(string = '') ⇒ Object (also: #to_s)
- #to_hash ⇒ Object
Methods included from Protoable
defined_filenames, defined_in, proto_contents, proto_filenames, retrieve_header
Constructor Details
#initialize(values = {}) ⇒ Message
Returns a new instance of Message.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/protobuf/message/message.rb', line 101 def initialize(values={}) @values = {} self.class.fields.dup.each do |tag, field| unless field.ready? field = field.setup self.class.fields[tag] = field self.class.__send__(:clear_field_cache) end if field.repeated? @values[field.name] = Field::FieldArray.new(field) end end values.each {|name, val| self.__send__("#{name}=", val)} end |
Class Method Details
.clear_field_cache ⇒ Object
:nodoc:
77 78 79 80 |
# File 'lib/protobuf/message/message.rb', line 77 def clear_field_cache @field_dictionary = nil @sorted_fields = nil end |
.define_field(rule, type, fname, tag, options) ⇒ Object
Define a field. Don't use this method directly.
37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/protobuf/message/message.rb', line 37 def define_field(rule, type, fname, tag, ) if [:extension] && ! extension_tag?(tag) raise RangeError, "#{tag} is not in #{@extension_tag}" end if fields.include?(tag) raise TagCollisionError, "Field tag #{tag} has already been used in #{self.name}." end fields[tag] = Field.build(self, rule, type, fname, tag, ) clear_field_cache end |
.descriptor ⇒ Object
96 97 98 |
# File 'lib/protobuf/message/message.rb', line 96 def descriptor @descriptor ||= Descriptor::Descriptor.new(self) end |
.extension_tag?(tag) ⇒ Boolean
49 50 51 |
# File 'lib/protobuf/message/message.rb', line 49 def extension_tag?(tag) @extension_tag.include?(tag) end |
.extensions(range) ⇒ Object
Reserve field numbers for extensions. Don't use this method directly.
17 18 19 |
# File 'lib/protobuf/message/message.rb', line 17 def extensions(range) @extension_tag = range end |
.field_dictionary ⇒ Object
:nodoc:
65 66 67 68 69 70 71 72 73 |
# File 'lib/protobuf/message/message.rb', line 65 def field_dictionary return @field_dictionary if @field_dictionary @field_dictionary = fields.dup fields.each do |_, field| @field_dictionary[field.name] = field @field_dictionary[field.name.to_s] = field end @field_dictionary end |
.fields ⇒ Object
A collection of field object.
54 55 56 |
# File 'lib/protobuf/message/message.rb', line 54 def fields @fields ||= {} end |
.get_field(tag_or_name) ⇒ Object
Find a field object by tag_or_name.
84 85 86 87 88 89 90 91 |
# File 'lib/protobuf/message/message.rb', line 84 def get_field(tag_or_name) case tag_or_name when Integer, String, Symbol field_dictionary[tag_or_name] else raise TypeError, tag_or_name.class end end |
.get_field_by_name ⇒ Object
Find a field object by tag_or_name.
for compatibility
94 95 96 97 98 99 100 101 |
# File 'lib/protobuf/message/message.rb', line 94 def get_field(tag_or_name) case tag_or_name when Integer, String, Symbol field_dictionary[tag_or_name] else raise TypeError, tag_or_name.class end end |
.get_field_by_tag ⇒ Object
Find a field object by tag_or_name.
for compatibility
93 94 95 96 97 98 99 100 |
# File 'lib/protobuf/message/message.rb', line 93 def get_field(tag_or_name) case tag_or_name when Integer, String, Symbol field_dictionary[tag_or_name] else raise TypeError, tag_or_name.class end end |
.optional(type, name, tag, options = {}) ⇒ Object
Define a optional field. Don't use this method directly.
27 28 29 |
# File 'lib/protobuf/message/message.rb', line 27 def optional(type, name, tag, ={}) define_field(:optional, type, name, tag, ) end |
.repeated(type, name, tag, options = {}) ⇒ Object
Define a repeated field. Don't use this method directly.
32 33 34 |
# File 'lib/protobuf/message/message.rb', line 32 def repeated(type, name, tag, ={}) define_field(:repeated, type, name, tag, ) end |
.required(type, name, tag, options = {}) ⇒ Object
Define a required field. Don't use this method directly.
22 23 24 |
# File 'lib/protobuf/message/message.rb', line 22 def required(type, name, tag, ={}) define_field(:required, type, name, tag, ) end |
.sorted_fields ⇒ Object
A collection of field object, which is sorted by tag number.
59 60 61 |
# File 'lib/protobuf/message/message.rb', line 59 def sorted_fields @sorted_fields ||= fields.sort_by {|tag, _| tag} end |
Instance Method Details
#==(obj) ⇒ Object
128 129 130 131 132 133 134 |
# File 'lib/protobuf/message/message.rb', line 128 def ==(obj) return false unless obj.is_a?(self.class) each_field do |field, value| return false unless value == obj.__send__(field.name) end true end |
#[](tag_or_name) ⇒ Object
259 260 261 262 263 264 265 |
# File 'lib/protobuf/message/message.rb', line 259 def [](tag_or_name) if field = get_field(tag_or_name) __send__(field.name) else raise NoMethodError, "No such field: #{tag_or_name.inspect}" end end |
#[]=(tag_or_name, value) ⇒ Object
267 268 269 270 271 272 273 |
# File 'lib/protobuf/message/message.rb', line 267 def []=(tag_or_name, value) if field = get_field(tag_or_name) __send__("#{field.name}=", value) else raise NoMethodError, "No such field: #{tag_or_name.inspect}" end end |
#clear! ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/protobuf/message/message.rb', line 136 def clear! @values.delete_if do |_, value| if value.is_a?(Field::FieldArray) value.clear false else true end end self end |
#clone ⇒ Object
152 153 154 |
# File 'lib/protobuf/message/message.rb', line 152 def clone copy_to(super, :clone) end |
#dup ⇒ Object
148 149 150 |
# File 'lib/protobuf/message/message.rb', line 148 def dup copy_to(super, :dup) end |
#each_field ⇒ Object
Iterate over a field collection. message.each_field do |field_object, value| # do something end
299 300 301 302 303 304 |
# File 'lib/protobuf/message/message.rb', line 299 def each_field self.class.__send__(:sorted_fields).each do |_, field| value = __send__(field.name) yield(field, value) end end |
#fields ⇒ Object
Returns a hash; which key is a tag number, and value is a field object.
276 277 278 |
# File 'lib/protobuf/message/message.rb', line 276 def fields self.class.fields end |
#get_field(tag_or_name) ⇒ Object
Returns field object or nil.
291 292 293 |
# File 'lib/protobuf/message/message.rb', line 291 def get_field(tag_or_name) self.class.get_field(tag_or_name) end |
#get_field_by_name(name) ⇒ Object
Returns field object or nil.
281 282 283 |
# File 'lib/protobuf/message/message.rb', line 281 def get_field_by_name(name) self.class.get_field_by_name(name) end |
#get_field_by_tag(tag) ⇒ Object
Returns field object or nil.
286 287 288 |
# File 'lib/protobuf/message/message.rb', line 286 def get_field_by_tag(tag) self.class.get_field_by_tag(tag) end |
#has_field?(tag_or_name) ⇒ Boolean
122 123 124 125 126 |
# File 'lib/protobuf/message/message.rb', line 122 def has_field?(tag_or_name) field = get_field(tag_or_name) raise ArgumentError, "unknown field: #{tag_or_name.inspect}" unless field @values.has_key?(field.name) end |
#initialized? ⇒ Boolean
118 119 120 |
# File 'lib/protobuf/message/message.rb', line 118 def initialized? fields.all? {|tag, field| field.initialized?(self) } end |
#inspect(indent = 0) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/protobuf/message/message.rb', line 176 def inspect(indent=0) result = [] i = ' ' * indent field_value_to_string = lambda {|field, value| result << \ if field.optional? && ! @values.has_key?(field.name) '' else case field when Field::MessageField if value.nil? "#{i}#{field.name} {}\n" else "#{i}#{field.name} {\n#{value.inspect(indent + 1)}#{i}}\n" end when Field::EnumField if value.is_a?(EnumValue) "#{i}#{field.name}: #{value.name}\n" else "#{i}#{field.name}: #{field.type.name_by_value(value)}\n" end else "#{i}#{field.name}: #{value.inspect}\n" end end } each_field do |field, value| if field.repeated? value.each do |v| field_value_to_string.call(field, v) end else field_value_to_string.call(field, value) end end result.join end |
#merge_from(message) ⇒ Object
255 256 257 |
# File 'lib/protobuf/message/message.rb', line 255 def merge_from() fields.each {|tag, field| field.merge(self, .__send__(field.name))} end |
#parse_from(stream) ⇒ Object
228 229 230 |
# File 'lib/protobuf/message/message.rb', line 228 def parse_from(stream) Decoder.decode(stream, self) end |
#parse_from_file(filename) ⇒ Object
218 219 220 221 222 223 224 225 226 |
# File 'lib/protobuf/message/message.rb', line 218 def parse_from_file(filename) if filename.is_a?(File) parse_from(filename) else File.open(filename, 'rb') do |f| parse_from(f) end end end |
#parse_from_string(string) ⇒ Object
214 215 216 |
# File 'lib/protobuf/message/message.rb', line 214 def parse_from_string(string) parse_from(StringIO.new(string)) end |
#serialize_to(stream) ⇒ Object
251 252 253 |
# File 'lib/protobuf/message/message.rb', line 251 def serialize_to(stream) Encoder.encode(stream, self) end |
#serialize_to_file(filename) ⇒ Object
241 242 243 244 245 246 247 248 249 |
# File 'lib/protobuf/message/message.rb', line 241 def serialize_to_file(filename) if filename.is_a?(File) serialize_to(filename) else File.open(filename, 'wb') do |f| serialize_to(f) end end end |
#serialize_to_string(string = '') ⇒ Object Also known as: to_s
232 233 234 235 236 237 238 |
# File 'lib/protobuf/message/message.rb', line 232 def serialize_to_string(string='') io = StringIO.new(string) serialize_to(io) result = io.string result.force_encoding(Encoding::BINARY) if result.respond_to?(:force_encoding) result end |
#to_hash ⇒ Object
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/protobuf/message/message.rb', line 306 def to_hash hash = {} each_field do |field, value| next unless @values.has_key?(field.name) case value when Array next if value.empty? hash[field.name] = value.map {|val| val.is_a?(Message) ? val.to_hash : val} when Message hash[field.name] = value.to_hash when EnumValue hash[field.name] = value.name else hash[field.name] = value end end hash end |