Class: Protobuf::Enum

Inherits:
SimpleDelegator
  • Object
show all
Defined in:
lib/protobuf/enum.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent_class, name, tag) ⇒ Enum

Instance Methods



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

def initialize(parent_class, name, tag)
  self.parent_class = parent_class
  self.name = name
  self.tag = tag
  super(tag)
end

Class Attribute Details

.enumsObject (readonly)

Returns the value of attribute enums.



76
77
78
# File 'lib/protobuf/enum.rb', line 76

def enums
  @enums
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



254
255
256
# File 'lib/protobuf/enum.rb', line 254

def name
  @name
end

#parent_classObject

Returns the value of attribute parent_class.



254
255
256
# File 'lib/protobuf/enum.rb', line 254

def parent_class
  @parent_class
end

#tagObject Also known as: to_i, to_hash_value, to_json_hash_value

Returns the value of attribute tag.



254
255
256
# File 'lib/protobuf/enum.rb', line 254

def tag
  @tag
end

Class Method Details

.aliases_allowed?Boolean

Returns:

  • (Boolean)


15
16
17
# File 'lib/protobuf/enum.rb', line 15

def self.aliases_allowed?
  get_option(:allow_alias)
end

.all_tagsObject

Public: Get all integer tags defined by this enum.

Examples

class StateMachine < ::Protobuf::Enum set_option :allow_alias define :ON, 1 define :STARTED, 1 define :OFF, 2 end

StateMachine.all_tags #=> [ 1, 2 ]

Returns an array of unique integers.



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

def self.all_tags
  @all_tags ||= enums.map(&:to_i).uniq
end

.define(name, tag) ⇒ Object

Internal: DSL method to create a new Enum. The given name will become a constant for this Enum pointing to the new instance.

Examples

class StateMachine < ::Protobuf::Enum define :ON, 1 define :OFF, 2 end

StateMachine::ON #=> #StateMachine::ON=1 StateMachine::OFF #=> #StateMachine::OFF=2

Returns nothing.



53
54
55
56
57
58
59
60
61
62
# File 'lib/protobuf/enum.rb', line 53

def self.define(name, tag)
  enum = new(self, name, tag)
  @enums ||= []
  @enums << enum
  # defining a new field for the enum will cause cached @values and @mapped_enums
  # to be incorrect; reset them
  @mapped_enums = @values = nil
  const_set(name, enum)
  mapped_enums
end

.enum_for_name(name) ⇒ Object

Public: Get the Enum associated with the given name.

name - A string-like object. Case-sensitive.

Example

class StateMachine < ::Protobuf::Enum define :ON, 1 define :OFF, 2 end

StateMachine.enum_for_name(:ON) # => #StateMachine::ON=1 StateMachine.enum_for_name("ON") # => #StateMachine::ON=1 StateMachine.enum_for_name(:on) # => nil StateMachine.enum_for_name(:FOO) # => nil

Returns the Enum object with the given name or nil.



119
120
121
122
123
# File 'lib/protobuf/enum.rb', line 119

def self.enum_for_name(name)
  const_get(name)
rescue ::NameError
  nil
end

.enum_for_tag(tag) ⇒ Object

Public: Get the Enum object corresponding to the given tag.

tag - An object that responds to to_i.

Returns an Enum object or nil. If the tag corresponds to multiple Enums, the first enum defined will be returned.



132
133
134
# File 'lib/protobuf/enum.rb', line 132

def self.enum_for_tag(tag)
  tag && (mapped_enums[tag.to_i] || []).first
end

.enum_for_tag_integer(tag) ⇒ Object



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

def self.enum_for_tag_integer(tag)
  (@mapped_enums[tag] || []).first
end

.enums_for_tag(tag) ⇒ Object

Public: Get an array of Enum objects with the given tag.

tag - An object that responds to to_i.

Examples

class StateMachine < ::Protobuf::Enum set_option :allow_alias define :ON, 1 define :STARTED, 1 define :OFF, 2 end

StateMachine.enums_for_tag(1) #=> [ #StateMachine::ON=1, #StateMachine::STARTED=1 ] StateMachine.enums_for_tag(2) #=> [ #StateMachine::OFF=2 ]

Returns an array with zero or more Enum objects or nil.



97
98
99
# File 'lib/protobuf/enum.rb', line 97

def self.enums_for_tag(tag)
  tag && mapped_enums[tag.to_i] || []
end

.fetch(candidate) ⇒ Object

Public: Get an Enum by a variety of type-checking mechanisms.

candidate - An Enum, Numeric, String, or Symbol object.

Example

class StateMachine < ::Protobuf::Enum set_option :allow_alias define :ON, 1 define :STARTED, 1 define :OFF, 2 end

StateMachine.fetch(StateMachine::ON) # => #StateMachine::ON=1 StateMachine.fetch(:ON) # => #StateMachine::ON=1 StateMachine.fetch("STARTED") # => #StateMachine::STARTED=1 StateMachine.fetch(1) # => [ #StateMachine::ON=1, #StateMachine::STARTED=1 ]

Returns an Enum object or nil.



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

def self.fetch(candidate)
  return enum_for_tag_integer(candidate) if candidate.is_a?(::Integer)

  case candidate
  when self
    candidate
  when ::Numeric
    enum_for_tag(candidate.to_i)
  when ::String, ::Symbol
    enum_for_name(candidate)
  else
    nil
  end
end

.mapped_enumsObject

Internal: A mapping of enum number -> enums defined used for speeding up our internal enum methods.



66
67
68
69
70
71
# File 'lib/protobuf/enum.rb', line 66

def self.mapped_enums
  @mapped_enums ||= enums.each_with_object({}) do |enum, hash|
    list = hash[enum.to_i] ||= []
    list << enum
  end
end

.name_for_tag(tag) ⇒ Object

Public: Get the Symbol name associated with the given number.

number - An object that responds to to_i.

Examples

# Without aliases class StateMachine < ::Protobuf::Enum define :ON, 1 define :OFF, 2 end

StateMachine.name_for_tag(1) # => :ON StateMachine.name_for_tag(2) # => :OFF StateMachine.name_for_tag(3) # => nil

# With aliases class StateMachine < ::Protobuf::Enum set_option :allow_alias define :STARTED, 1 define :ON, 1 define :OFF, 2 end

StateMachine.name_for_tag(1) # => :STARTED StateMachine.name_for_tag(2) # => :OFF

Returns the symbol name of the enum constant given it's associated tag or nil. If the given tag has multiple names associated (due to allow_alias) the first defined name will be returned.



206
207
208
# File 'lib/protobuf/enum.rb', line 206

def self.name_for_tag(tag)
  enum_for_tag(tag).try(:name)
end

.valid_tag?(tag) ⇒ Boolean

Public: Check if the given tag is defined by this Enum.

number - An object that responds to to_i.

Returns a boolean.

Returns:

  • (Boolean)


216
217
218
# File 'lib/protobuf/enum.rb', line 216

def self.valid_tag?(tag)
  tag.respond_to?(:to_i) && mapped_enums.key?(tag.to_i)
end

.valuesObject

Public: [DEPRECATED] Return a hash of Enum objects keyed by their :name.



223
224
225
226
227
# File 'lib/protobuf/enum.rb', line 223

def self.values
  @values ||= enums.each_with_object({}) do |enum, hash|
    hash[enum.name] = enum
  end
end

Instance Method Details

#==(other) ⇒ Object

Custom equality method since otherwise identical values from different enums will be considered equal by Integer's equality method (or Fixnum's on Ruby < 2.4.0).



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

def ==(other)
  if other.is_a?(Protobuf::Enum)
    parent_class == other.parent_class && tag == other.tag
  elsif tag.class == other.class
    tag == other
  else
    false
  end
end

#classObject

Overriding the class so ActiveRecord/Arel visitor will visit the enum as an Integer.



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

def class
  # This is done for backward compatibility for < 2.4.0. This ensures that
  # if Ruby version >= 2.4.0, this will return Integer. If below, then will
  # return Fixnum.
  #
  # This prevents the constant deprecation warnings on Fixnum.
  tag.class
end

#eql?(other) ⇒ Boolean

Protobuf::Enum delegates methods to Fixnum, which has a custom hash equality method (eql?) This causes enum values to be equivalent when using ==, ===, equals?, but not eql?**:

2.3.7 :002 > ::Test::EnumTestType::ZERO.eql?(::Test::EnumTestType::ZERO) => false

However, they are equilvalent to their tag value:

2.3.7 :002 > ::Test::EnumTestType::ZERO.eql?(::Test::EnumTestType::ZERO.tag) => true

**The implementation changed in Ruby 2.5, so this only affects Ruby versions less than v2.4.

Use the hash equality implementation from Object#eql?, which is equivalent to == instead.

Returns:

  • (Boolean)


308
309
310
# File 'lib/protobuf/enum.rb', line 308

def eql?(other)
  self == other
end

#inspectObject



312
313
314
# File 'lib/protobuf/enum.rb', line 312

def inspect
  "\#<Protobuf::Enum(#{parent_class})::#{name}=#{tag}>"
end

#to_intObject



316
317
318
# File 'lib/protobuf/enum.rb', line 316

def to_int
  tag.to_int
end

#to_jsonObject

This fixes a reflection bug in JrJackson RubyAnySerializer that does not render Protobuf enums correctly because to_json is not defined. It takes any number of arguments to support the JSON gem trying to pass an argument. NB: This method is required to return a string and not an integer.



325
326
327
# File 'lib/protobuf/enum.rb', line 325

def to_json(*)
  to_s
end

#to_s(format = :tag) ⇒ Object



329
330
331
332
333
334
335
336
337
338
# File 'lib/protobuf/enum.rb', line 329

def to_s(format = :tag)
  case format
  when :tag
    to_i.to_s
  when :name
    name.to_s
  else
    to_i.to_s
  end
end

#try(*args, &block) ⇒ Object

Re-implement try in order to fix the problem where the underlying fixnum doesn't respond to all methods (e.g. name or tag). If we respond to the first argument, __send__ the args. Otherwise, delegate the try call to the underlying vlaue fixnum.



345
346
347
348
349
350
351
352
353
354
# File 'lib/protobuf/enum.rb', line 345

def try(*args, &block)
  case
  when args.empty? && block_given?
    yield self
  when respond_to?(args.first)
    __send__(*args, &block)
  else
    @tag.try(*args, &block)
  end
end