Class: Protopuffs::Message::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/protopuffs/message/base.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(field_values = nil) ⇒ Base

Returns a new instance of Base.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/protopuffs/message/base.rb', line 41

def initialize(field_values = nil)
  if self.class == Base
    raise "#{self.class} should not be instantiated directly. Use the factory #{self.class}.define_message_class instead."
  end

  if field_values.nil?
    @buffer = StringIO.new
    @buffer.set_encoding("BINARY") if @buffer.respond_to?(:set_encoding)
  elsif field_values.respond_to?(:each_pair)
    @buffer = StringIO.new
    @buffer.set_encoding("BINARY") if @buffer.respond_to?(:set_encoding)
    self.attributes = field_values
  else
    from_wire_format(field_values)
  end
end

Class Attribute Details

.fieldsObject (readonly)

Returns the value of attribute fields.



9
10
11
# File 'lib/protopuffs/message/base.rb', line 9

def fields
  @fields
end

Instance Attribute Details

#bufferObject (readonly)

Returns the value of attribute buffer.



39
40
41
# File 'lib/protopuffs/message/base.rb', line 39

def buffer
  @buffer
end

Class Method Details

.check_fields_for_errors(name, fields) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/protopuffs/message/base.rb', line 23

def check_fields_for_errors(name, fields)
  tags = fields.map { |field| field.tag }
  if tags.uniq.size != fields.size
    raise ParseError, "A tag was reused in the descriptor for message #{name}. Please check that each tag is unique."
  end

  if tags.any? { |tag| tag < 1 || tag > 536_870_911 }
    raise ParseError, "A tag is out of range in the descriptor for message #{name}. Please check that each tag is in the range 1 <= x <= 536,870,911."
  end

  if tags.any? { |tag| (19000..19999).include?(tag) }
    raise ParseError, "A tag is invalid in the descriptor for message #{name}. Please check that each tag is not in the reserved range 19,000 <= x <= 19,999."
  end
end

.define_message_class(name, fields) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/protopuffs/message/base.rb', line 11

def define_message_class(name, fields)
  name = name.delete("_")
  self.check_fields_for_errors(name, fields)
  Message.send(:remove_const, name) if Message.const_defined?(name)
  klass = Message.const_set(name, Class.new(self))
  klass.instance_variable_set(:@fields, fields)
  fields.each do |field|
    klass.send(:attr_accessor, field.identifier)
  end
  klass
end

Instance Method Details

#==(other) ⇒ Object



113
114
115
116
117
118
119
# File 'lib/protopuffs/message/base.rb', line 113

def ==(other)
  return false if self.class != other.class
  self.class.fields.each do |field|
    return false if send(field.identifier) != other.send(field.identifier)
  end
  true
end

#attributes=(attrs = {}) ⇒ Object



107
108
109
110
111
# File 'lib/protopuffs/message/base.rb', line 107

def attributes=(attrs = {})
  attrs.each_pair do |name, value|
    self.send("#{name}=", value) if respond_to?("#{name}=")
  end
end

#from_wire_format(buffer) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/protopuffs/message/base.rb', line 73

def from_wire_format(buffer)
  if !buffer.respond_to?(:read)
    buffer.force_encoding("BINARY") if buffer.respond_to?(:force_encoding)
    @buffer = StringIO.new(buffer)
  else
    @buffer = buffer
  end
  @buffer.set_encoding("BINARY") if @buffer.respond_to?(:set_encoding)

  until @buffer.eof?
    tag = MessageField.shift_tag(@buffer)
    field = self.class.fields.find { |f| f.tag == tag }
    next if field.nil?
    value_bytes = field.class.shift(@buffer)

    value = field.decode(value_bytes)
    if field.repeated? && send(field.identifier).nil?
      send("#{field.identifier}=", [value])
    elsif field.repeated?
      send(field.identifier) << value
    else
      send("#{field.identifier}=", value)
    end
  end
  set_values_for_missing_optional_fields
  self
end

#inspectObject

Returns the protocol buffer text format, which is useful for debugging



67
68
69
70
71
# File 'lib/protopuffs/message/base.rb', line 67

def inspect
  type = self.class.name.split("::").last.downcase
  field_strings = self.class.fields.map { |f| "  #{f.identifier}: #{send(f.identifier).inspect}\n" }
  "#{type} {\n#{field_strings.join}}"
end

#set_values_for_missing_optional_fieldsObject



101
102
103
104
105
# File 'lib/protopuffs/message/base.rb', line 101

def set_values_for_missing_optional_fields
  self.class.fields.select { |field| field.optional? }.each do |field|
    send("#{field.identifier}=", field.default) if send(field.identifier).nil?
  end
end

#to_wire_formatObject



58
59
60
61
62
63
64
# File 'lib/protopuffs/message/base.rb', line 58

def to_wire_format
  self.class.fields.sort_by { |f| f.tag }.each do |field|
    value = send(field.identifier)
    @buffer.write field.to_wire_format_with_value(value) unless value.nil?
  end
  @buffer.string
end