Class: Protobuf::Message

Inherits:
Object
  • Object
show all
Extended by:
Protoable
Defined in:
lib/protobuf/message/message.rb

Defined Under Namespace

Classes: ExtensionFields, TagCollisionError

Class Method Summary collapse

Instance Method Summary collapse

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.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/protobuf/message/message.rb', line 108

def initialize(values={})
  @values = {}

  self.class.fields.each do |tag, field|
    unless field.ready?
      field = field.setup
      self.class.class_eval {@fields[tag] = field}
    end
    if field.repeated?
      @values[field.name] = Protobuf::Field::FieldArray.new(field)
    end
  end

  # TODO
  self.class.extension_fields.each do |tag, field|
    unless field.ready?
      field = field.setup
      self.class.class_eval {@extension_fields[tag] = field}
    end
    if field.repeated?
      @values[field.name] = Protobuf::Field::FieldArray.new(field)
    end
  end

  values.each {|tag, val| self[tag] = val}
end

Class Method Details

.define_field(rule, type, fname, tag, opts = {}) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/protobuf/message/message.rb', line 50

def define_field(rule, type, fname, tag, opts={})
  field_hash = opts[:extension] ? extension_fields : (@fields ||= {})
  raise Protobuf::Message::TagCollisionError.new(<<-eos.strip) if field_hash.keys.include? tag
    Field number #{tag} has already been used in "#{self.name}" by field "#{fname}".
  eos
  field_hash[tag] = Protobuf::Field.build self, rule, type, fname, tag, opts
end

.descriptorObject



103
104
105
# File 'lib/protobuf/message/message.rb', line 103

def descriptor
  @descriptor ||= Protobuf::Descriptor::Descriptor.new(self)
end

.extension_fieldsObject



62
63
64
# File 'lib/protobuf/message/message.rb', line 62

def extension_fields
  @extension_fields ||= ExtensionFields.new
end

.extension_tag?(tag) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
# File 'lib/protobuf/message/message.rb', line 58

def extension_tag?(tag)
  extension_fields.include_tag? tag
end

.extensions(range) ⇒ Object



34
35
36
# File 'lib/protobuf/message/message.rb', line 34

def extensions(range)
  @extension_fields = ExtensionFields.new range
end

.fieldsObject



32
# File 'lib/protobuf/message/message.rb', line 32

def fields; @fields ||= {} end

.get_ext_field(tag_or_name) ⇒ Object

TODO merge to get_field



95
96
97
98
99
100
101
# File 'lib/protobuf/message/message.rb', line 95

def get_ext_field(tag_or_name)
  case tag_or_name
  when Integer; get_ext_field_by_tag tag_or_name
  when String, Symbol; get_ext_field_by_name tag_or_name
  else; raise TypeError.new(tag_or_name.class)
  end
end

.get_ext_field_by_name(name) ⇒ Object

TODO merge to get_field_by_name



84
85
86
87
# File 'lib/protobuf/message/message.rb', line 84

def get_ext_field_by_name(name)
  name = name.to_sym
  extension_fields.values.find {|field| field.name == name}
end

.get_ext_field_by_tag(tag) ⇒ Object

TODO merge to get_field_by_tag



90
91
92
# File 'lib/protobuf/message/message.rb', line 90

def get_ext_field_by_tag(tag)
  extension_fields[tag]
end

.get_field(tag_or_name) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/protobuf/message/message.rb', line 75

def get_field(tag_or_name)
  case tag_or_name
  when Integer; get_field_by_tag tag_or_name
  when String, Symbol; get_field_by_name tag_or_name
  else; raise TypeError.new(tag_or_name.class)
  end
end

.get_field_by_name(name) ⇒ Object



66
67
68
69
# File 'lib/protobuf/message/message.rb', line 66

def get_field_by_name(name)
  name = name.to_sym
  fields.values.find {|field| field.name == name}
end

.get_field_by_tag(tag) ⇒ Object



71
72
73
# File 'lib/protobuf/message/message.rb', line 71

def get_field_by_tag(tag)
  fields[tag]
end

.optional(type, name, tag, opts = {}) ⇒ Object



42
43
44
# File 'lib/protobuf/message/message.rb', line 42

def optional(type, name, tag, opts={})
  define_field :optional, type, name, tag, opts
end

.repeated(type, name, tag, opts = {}) ⇒ Object



46
47
48
# File 'lib/protobuf/message/message.rb', line 46

def repeated(type, name, tag, opts={})
  define_field :repeated, type, name, tag, opts
end

.required(type, name, tag, opts = {}) ⇒ Object



38
39
40
# File 'lib/protobuf/message/message.rb', line 38

def required(type, name, tag, opts={})
  define_field :required, type, name, tag, opts
end

Instance Method Details

#==(obj) ⇒ Object



146
147
148
149
150
151
152
# File 'lib/protobuf/message/message.rb', line 146

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



277
278
279
280
281
282
283
# File 'lib/protobuf/message/message.rb', line 277

def [](tag_or_name)
  if field = get_field(tag_or_name) || get_ext_field(tag_or_name)
    send field.name
  else
    raise NoMethodError.new("No such field: #{tag_or_name.inspect}")
  end
end

#[]=(tag_or_name, value) ⇒ Object



285
286
287
288
289
290
291
# File 'lib/protobuf/message/message.rb', line 285

def []=(tag_or_name, value)
  if field = get_field(tag_or_name) || get_ext_field(tag_or_name)
    send "#{field.name}=", value
  else
    raise NoMethodError.new("No such field: #{tag_or_name.inspect}")
  end
end

#clear!Object



154
155
156
157
158
# File 'lib/protobuf/message/message.rb', line 154

def clear!
  each_field do |field, value|
    field.clear self
  end
end

#dupObject



160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/protobuf/message/message.rb', line 160

def dup
  ret = self.class.new
  each_field do |field, value|
    if field.repeated?
      field_array = ret.send(field.name)
      value.each do |v|
        field_array << (v.is_a?(Numeric) ? v : v.dup)
      end
    else
      ret.send("#{field.name}=", value.is_a?(Numeric) ? value : value.dup)
    end
  end
  ret
end

#each_fieldObject



303
304
305
306
307
# File 'lib/protobuf/message/message.rb', line 303

def each_field
  (fields.merge extension_fields).sort_by {|tag, field| tag}.each do |tag, field|
    yield field, send(field.name)
  end
end

#extension_fieldsObject



298
# File 'lib/protobuf/message/message.rb', line 298

def extension_fields; self.class.extension_fields end

#fieldsObject



293
# File 'lib/protobuf/message/message.rb', line 293

def fields; self.class.fields end

#get_ext_field(tag_or_name) ⇒ Object



301
# File 'lib/protobuf/message/message.rb', line 301

def get_ext_field(tag_or_name); self.class.get_ext_field(tag_or_name) end

#get_ext_field_by_name(name) ⇒ Object



299
# File 'lib/protobuf/message/message.rb', line 299

def get_ext_field_by_name(name); self.class.get_ext_field_by_name(name) end

#get_ext_field_by_tag(tag) ⇒ Object



300
# File 'lib/protobuf/message/message.rb', line 300

def get_ext_field_by_tag(tag); self.class.get_ext_field_by_tag(tag) end

#get_field(tag_or_name) ⇒ Object



296
# File 'lib/protobuf/message/message.rb', line 296

def get_field(tag_or_name); self.class.get_field(tag_or_name) end

#get_field_by_name(name) ⇒ Object



294
# File 'lib/protobuf/message/message.rb', line 294

def get_field_by_name(name); self.class.get_field_by_name(name) end

#get_field_by_tag(tag) ⇒ Object



295
# File 'lib/protobuf/message/message.rb', line 295

def get_field_by_tag(tag); self.class.get_field_by_tag(tag) end

#has_field?(tag_or_name) ⇒ Boolean

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


140
141
142
143
144
# File 'lib/protobuf/message/message.rb', line 140

def has_field?(tag_or_name)
  field = get_field(tag_or_name) || get_ext_field(tag_or_name)
  raise ArgumentError.new("unknown field: #{tag_or_name.inspect}") unless field
  @values.has_key?(field.name)
end

#initialized?Boolean

Returns:

  • (Boolean)


135
136
137
138
# File 'lib/protobuf/message/message.rb', line 135

def initialized?
  fields.all? {|tag, field| field.initialized?(self) } && \
  extension_fields.all? {|tag, field| field.initialized?(self) }
end

#inspect(indent = 0) ⇒ Object



175
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
213
214
215
216
217
218
# File 'lib/protobuf/message/message.rb', line 175

def inspect(indent=0)
  ret = ''
  i = '  ' * indent
  field_value_to_string = lambda do |field, value|
    ret +=
      if field.is_a? Protobuf::Field::MessageField
        if value.nil?
          if $DEBUG
            "#{i}#{field.name} {\n#{'  ' * (indent + 1)}nil\n#{i}}\n"
          else
            "#{i}#{field.name} {}\n"
          end
        else
          "#{i}#{field.name} {\n#{value.inspect(indent + 1)}#{i}}\n"
        end
      elsif field.is_a? Protobuf::Field::EnumField
 if field.optional? and not has_field?(field.name)
   ''
 else
          "#{i}#{field.name}: #{field.type.name_by_value(value)}\n"
        end
      else
        if $DEBUG
          "#{i}#{field.name}: #{value.inspect}\n"
        else
          if field.optional? and not has_field?(field.name)
            ''
          else
            "#{i}#{field.name}: #{value.inspect}\n"
          end
        end
      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
  ret
end

#merge_field(tag, value) ⇒ Object



272
273
274
275
# File 'lib/protobuf/message/message.rb', line 272

def merge_field(tag, value)
  #get_field_by_tag(tag).merge self, bytes #TODO
  (get_field_by_tag(tag) or get_ext_field_by_tag(tag)).merge self, value
end

#merge_from(message) ⇒ Object



261
262
263
264
265
# File 'lib/protobuf/message/message.rb', line 261

def merge_from(message)
  # TODO
  fields.each {|tag, field| merge_field tag, message[tag]}
  self.class.extension_fields.each {|tag, field| merge_field tag, message[tag]}
end

#parse_from(stream) ⇒ Object



234
235
236
# File 'lib/protobuf/message/message.rb', line 234

def parse_from(stream)
  Protobuf::Decoder.decode stream, self
end

#parse_from_file(filename) ⇒ Object



224
225
226
227
228
229
230
231
232
# File 'lib/protobuf/message/message.rb', line 224

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



220
221
222
# File 'lib/protobuf/message/message.rb', line 220

def parse_from_string(string)
  parse_from StringIO.new(string)
end

#serialize_to(stream) ⇒ Object



257
258
259
# File 'lib/protobuf/message/message.rb', line 257

def serialize_to(stream)
  Protobuf::Encoder.encode stream, self
end

#serialize_to_file(filename) ⇒ Object



247
248
249
250
251
252
253
254
255
# File 'lib/protobuf/message/message.rb', line 247

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



238
239
240
241
242
243
244
# File 'lib/protobuf/message/message.rb', line 238

def serialize_to_string(string='')
  io = StringIO.new string
  serialize_to io
  result = io.string
  result.force_encoding('ASCII-8BIT') if result.respond_to?(:force_encoding)
  result
end

#set_field(tag, bytes) ⇒ Object



267
268
269
270
# File 'lib/protobuf/message/message.rb', line 267

def set_field(tag, bytes)
  field = (get_field_by_tag(tag) or get_ext_field_by_tag(tag))
  field.set self, bytes if field
end