Class: Protobug::Field

Inherits:
Object
  • Object
show all
Defined in:
lib/protobug/field.rb

Defined Under Namespace

Classes: BoolField, BytesField, DoubleField, EnumField, Fixed32Field, Fixed64Field, FloatField, GroupField, Int32Field, Int64Field, IntegerField, MapField, MessageField, SFixed32Field, SFixed64Field, SInt32Field, SInt64Field, StringField, UInt32Field, UInt64Field

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(number, name, json_name: nil, cardinality: :optional, oneof: nil, packed: false, proto3_optional: cardinality == :optional) ⇒ Field

Returns a new instance of Field.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/protobug/field.rb', line 10

def initialize(number, name, json_name: nil, cardinality: :optional, oneof: nil, packed: false,
               proto3_optional: cardinality == :optional)
  @number = number
  @name = name.to_sym
  @json_name = json_name || name.to_s
  @cardinality = cardinality || raise(ArgumentError, "cardinality is required")
  @oneof = oneof
  @setter = :"#{name}="
  @adder = :"add_#{name}" if repeated?
  @ivar = :"@#{name}"
  @clearer = :"clear_#{name}"
  @haser = :"#{name}?"
  @packed = packed
  @proto3_optional = proto3_optional
end

Instance Attribute Details

#adderObject

Returns the value of attribute adder.



7
8
9
# File 'lib/protobug/field.rb', line 7

def adder
  @adder
end

#cardinalityObject

Returns the value of attribute cardinality.



7
8
9
# File 'lib/protobug/field.rb', line 7

def cardinality
  @cardinality
end

#clearerObject

Returns the value of attribute clearer.



7
8
9
# File 'lib/protobug/field.rb', line 7

def clearer
  @clearer
end

#haserObject

Returns the value of attribute haser.



7
8
9
# File 'lib/protobug/field.rb', line 7

def haser
  @haser
end

#ivarObject

Returns the value of attribute ivar.



7
8
9
# File 'lib/protobug/field.rb', line 7

def ivar
  @ivar
end

#json_nameObject

Returns the value of attribute json_name.



7
8
9
# File 'lib/protobug/field.rb', line 7

def json_name
  @json_name
end

#nameObject

Returns the value of attribute name.



7
8
9
# File 'lib/protobug/field.rb', line 7

def name
  @name
end

#numberObject

Returns the value of attribute number.



7
8
9
# File 'lib/protobug/field.rb', line 7

def number
  @number
end

#oneofObject

Returns the value of attribute oneof.



7
8
9
# File 'lib/protobug/field.rb', line 7

def oneof
  @oneof
end

#setterObject

Returns the value of attribute setter.



7
8
9
# File 'lib/protobug/field.rb', line 7

def setter
  @setter
end

Instance Method Details

#binary_decode(binary, message, registry, wire_type) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/protobug/field.rb', line 110

def binary_decode(binary, message, registry, wire_type)
  if repeated? && wire_type == 2 && [0, 1, 5].include?(self.wire_type)
    len = StringIO.new(BinaryEncoding.decode_length(binary))
    len.binmode

    message.send(adder, binary_decode_one(len, message, registry, self.wire_type)) until len.eof?
  elsif wire_type != self.wire_type
    raise DecodeError, "wrong wire type for #{self}: #{wire_type.inspect}"
  else
    message.send(adder || setter, binary_decode_one(binary, message, registry, wire_type))
  end
end

#binary_encode(value, outbuf) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/protobug/field.rb', line 92

def binary_encode(value, outbuf)
  if repeated?
    if packed?
      binary_encode_packed(value, outbuf)
    else
      value.each do |v|
        BinaryEncoding.encode_varint (number << 3) | wire_type, outbuf
        binary_encode_one(v, outbuf)
      end
    end
  elsif (!optional? || !proto3_optional?) && !oneof && default == value
    # omit
  else
    BinaryEncoding.encode_varint (number << 3) | wire_type, outbuf
    binary_encode_one(value, outbuf)
  end
end

#define_adder(message) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/protobug/field.rb', line 64

def define_adder(message)
  field = self
  message.define_method(adder) do |value|
    field.validate!(value, self)

    existing = instance_variable_get(field.ivar)
    if UNSET == existing
      existing = field.default
      instance_variable_set(field.ivar, existing)
    end

    existing << value
  end
end

#json_decode(value, message, ignore_unknown_fields, registry) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/protobug/field.rb', line 148

def json_decode(value, message, ignore_unknown_fields, registry)
  if repeated?
    return if value.nil?

    unless value.is_a?(Array)
      raise DecodeError,
            "expected Array for #{inspect}, got #{value.inspect}"
    end

    value.map do |v|
      message.send(adder, json_decode_one(v, ignore_unknown_fields, registry))
    end
  else
    value = json_decode_one(value, ignore_unknown_fields, registry)
    message.send(setter, value) unless UNSET == value
  end
end

#json_encode(value, print_unknown_fields:) ⇒ Object



123
124
125
126
127
128
129
130
131
# File 'lib/protobug/field.rb', line 123

def json_encode(value, print_unknown_fields:)
  if repeated?
    value.map { |v| json_encode_one(v, print_unknown_fields: print_unknown_fields) }
  elsif (!optional? || !proto3_optional?) && !oneof && default == value
    # omit
  else
    json_encode_one(value, print_unknown_fields: print_unknown_fields)
  end
end

#json_key_encode(value) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/protobug/field.rb', line 133

def json_key_encode(value)
  case value
  when String
    value
  when Integer, Float
    value.to_s
  when TrueClass
    "true"
  when FalseClass
    "false"
  else
    raise EncodeError, "unexpected type for map key: #{value.inspect}"
  end
end

#optional?Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/protobug/field.rb', line 56

def optional?
  cardinality == :optional
end

#packed?Boolean

Returns:

  • (Boolean)


52
53
54
# File 'lib/protobug/field.rb', line 52

def packed?
  @packed
end

#pretty_print(pp) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/protobug/field.rb', line 26

def pretty_print(pp)
  pp.group 0, "#{self.class}.new(", ")" do
    pp.text @number.to_s
    pp.breakable(", ")
    pp.text(@name.inspect)
    pp.breakable(", ")
    if json_name != name.name
      pp.breakable(", ")
      pp.text("json_name: ")
      pp.text(@json_name.inspect)
    end
    pp.breakable(", ")
    pp.text("cardinality: ")
    pp.pp(@cardinality)
    if oneof
      pp.breakable(", ")
      pp.text("oneof: ")
      pp.text(@oneof.inspect)
    end
  end
end

#proto3_optional?Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/protobug/field.rb', line 60

def proto3_optional?
  @proto3_optional
end

#repeated?Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/protobug/field.rb', line 48

def repeated?
  cardinality == :repeated
end

#to_text(value) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/protobug/field.rb', line 79

def to_text(value)
  case [cardinality, json_scalar?]
  when [:repeated, true]
    Array(value).map { |v| "#{name}: #{scalar_to_text(v)}" }.join("\n")
  when [:repeated, false]
    Array(value).map { |v| "#{name} {\n#{v.to_text.gsub(/^/, "  ")}\n}" }.join("\n")
  when [:optional, true]
    "#{name}: #{scalar_to_text(value)}"
  when [:optional, false]
    "#{name} {\n#{value.to_text.gsub(/^/, "  ")}\n}"
  end
end

#validate!(value, message) ⇒ Object

Raises:



166
167
168
169
170
171
172
173
174
175
176
# File 'lib/protobug/field.rb', line 166

def validate!(value, message)
  raise DecodeError, "nil is invalid for #{name} in #{message}" if UNSET == value

  return unless oneof

  message.class.oneofs[oneof].each do |f|
    next if f == self

    message.send(f.clearer)
  end
end