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.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/protobuf/message/message.rb', line 106

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

  fields.each do |tag, field|
    unless field.ready?
      field = field.setup
      self.class.class_eval {@fields[tag] = field}
    end
    field.define_accessor self
  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
    field.define_accessor self
  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



101
102
103
# File 'lib/protobuf/message/message.rb', line 101

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



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

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



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

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

.get_ext_field_by_tag(tag) ⇒ Object

TODO merge to get_field_by_tag



88
89
90
# File 'lib/protobuf/message/message.rb', line 88

def get_ext_field_by_tag(tag)
  extension_fields[tag]
end

.get_field(tag_or_name) ⇒ Object



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

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
# File 'lib/protobuf/message/message.rb', line 66

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

.get_field_by_tag(tag) ⇒ Object



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

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



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

def ==(obj)
  return false unless obj.is_a? self.class
  each_field do |field, value|
    return false unless value == obj[field.name]
  end
  true
end

#[](tag_or_name) ⇒ Object



272
273
274
275
276
277
278
279
280
# File 'lib/protobuf/message/message.rb', line 272

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

#[]=(tag_or_name, value) ⇒ Object



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

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

#clear!Object



152
153
154
155
156
# File 'lib/protobuf/message/message.rb', line 152

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

#dupObject



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

def dup
  ret = self.class.new
  each_field do |field, value|
    if field.repeated?
      value.each do |v|
        ret[field.name] << (v.is_a?(Numeric) ? v : v.dup)
      end
    else
      ret[field.name] = value.is_a?(Numeric) ? value : value.dup
    end
  end
  ret
end

#each_field(&block) ⇒ Object



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

def each_field(&block)
  (fields.merge extension_fields).to_a.sort{|(t1, f1), (t2, f2)| t1 <=> t2}.each do |tag, field|
    block.call field, self[tag]
  end
end

#extension_fieldsObject



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

def extension_fields; self.class.extension_fields end

#fieldsObject



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

def fields; self.class.fields end

#get_ext_field(tag_or_name) ⇒ Object



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

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

#get_ext_field_by_name(name) ⇒ Object



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

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

#get_ext_field_by_tag(tag) ⇒ Object



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

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

#get_field(tag_or_name) ⇒ Object



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

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

#get_field_by_name(name) ⇒ Object



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

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

#get_field_by_tag(tag) ⇒ Object



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

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

#has_field?(tag_or_name) ⇒ Boolean

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


138
139
140
141
142
# File 'lib/protobuf/message/message.rb', line 138

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)


129
130
131
132
133
134
135
136
# File 'lib/protobuf/message/message.rb', line 129

def initialized?
  fields.to_a.inject(true) do |result, (tag, field)|
    result and field.initialized?(self)
  end and
  extension_fields.to_a.inject(true) do |result, (tag, field)|
    result and field.initialized?(self)
  end
end

#inspect(indent = 0) ⇒ Object



172
173
174
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
# File 'lib/protobuf/message/message.rb', line 172

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



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

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



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

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



231
232
233
# File 'lib/protobuf/message/message.rb', line 231

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

#parse_from_file(filename) ⇒ Object



221
222
223
224
225
226
227
228
229
# File 'lib/protobuf/message/message.rb', line 221

def parse_from_file(filename)
  if filename.is_a? File
    parse_from filename
  else
    File.open(filename, 'r') do |f|
      parse_from f
    end
  end
end

#parse_from_string(string) ⇒ Object



217
218
219
# File 'lib/protobuf/message/message.rb', line 217

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

#serialize_to(stream) ⇒ Object



252
253
254
# File 'lib/protobuf/message/message.rb', line 252

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

#serialize_to_file(filename) ⇒ Object



242
243
244
245
246
247
248
249
250
# File 'lib/protobuf/message/message.rb', line 242

def serialize_to_file(filename)
  if filename.is_a? File
    serialize_to filename
  else
    File.open(filename, 'w') do |f|
      serialize_to f
    end
  end
end

#serialize_to_string(string = '') ⇒ Object Also known as: to_s



235
236
237
238
239
# File 'lib/protobuf/message/message.rb', line 235

def serialize_to_string(string='')
  io = StringIO.new string
  serialize_to io
  io.string
end

#set_field(tag, bytes) ⇒ Object



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

def set_field(tag, bytes)
  #get_field_by_tag(tag).set self, bytes # TODO
  (get_field_by_tag(tag) or get_ext_field_by_tag(tag)).set self, bytes
end