module Protobuf::Message::Fields::ClassMethods

Public Instance Methods

all_fields() click to toggle source

Field Access Methods

# File lib/protobuf/message/fields.rb, line 81
def all_fields
  @all_fields ||= field_store.values.uniq.sort_by(&:tag)
end
define_field(rule, type_class, fully_qualified_field_name, tag, options) click to toggle source
# File lib/protobuf/message/fields.rb, line 128
def define_field(rule, type_class, fully_qualified_field_name, tag, options)
  raise_if_tag_collision(tag, fully_qualified_field_name)
  raise_if_name_collision(fully_qualified_field_name)

  # Determine appropirate accessor for fields depending on name collisions via extensions:

  # Case 1: Base field = "string_field" and no extensions of the same name
  # Result:
  #   message.string_field #=> @values["string_field"]
  #   message[:string_field] #=> @values["string_field"]
  #   message['string_field'] #=> @values["string_field"]

  # Case 2: Base field = "string_field" and extension 1 = ".my_package.string_field", extension N = ".package_N.string_field"...
  # Result:
  #   message.string_field #=> @values["string_field"]
  #   message[:string_field] #=> @values["string_field"]
  #   message['string_field'] #=> @values["string_field"]
  #   message[:'.my_package.string_field'] #=> @values[".my_package.string_field"]
  #   message['.my_package.string_field']  #=> @values[".my_package.string_field"]

  # Case 3: No base field, extension 1 = ".my_package.string_field", extension 2 = ".other_package.string_field", extension N...
  # Result:
  #   message.string_field #=> raise NoMethodError (no simple accessor allowed)
  #   message[:string_field] #=> raise NoMethodError (no simple accessor allowed)
  #   message['string_field'] #=> raise NoMethodError (no simple accessor allowed)
  #   message[:'.my_package.string_field'] #=> @values[".my_package.string_field"]
  #   message['.my_package.string_field']  #=> @values[".my_package.string_field"]
  #   message[:'.other_package.string_field'] #=> @values[".other_package.string_field"]
  #   message['.other_package.string_field']  #=> @values[".other_package.string_field"]

  # Case 4: No base field, extension = ".my_package.string_field", no other extensions
  # Result:
  #   message.string_field #=> @values[".my_package.string_field"]
  #   message[:string_field] #=> @values[".my_package.string_field"]
  #   message['string_field'] #=> @values[".my_package.string_field"]
  #   message[:'.my_package.string_field'] #=> @values[".my_package.string_field"]
  #   message[:'.my_package.string_field'] #=> @values[".my_package.string_field"]

  simple_name =
    if options[:extension]
      base_name = fully_qualified_field_name.to_s.split('.').last.to_sym
      if field_store[base_name]
        # Case 3
        if field_store[base_name].extension?
          remove_existing_accessors(base_name)
        end
        nil
      # Case 4
      else
        base_name
      end
    else
      # Case 1
      fully_qualified_field_name
    end

  field = ::Protobuf::Field.build(self, rule, type_class, fully_qualified_field_name,
                                  tag, simple_name, options)
  field_store[tag] = field
  field_store[fully_qualified_field_name.to_sym] = field
  field_store[fully_qualified_field_name.to_s] = field
  if simple_name && simple_name != fully_qualified_field_name
    field_store[simple_name.to_sym] = field
    field_store[simple_name.to_s] = field
  end
  # defining a new field for the message will cause cached @all_fields, @extension_fields,
  # and @fields to be incorrect; reset them
  @all_fields = @extension_fields = @fields = nil
end
extension_fields() click to toggle source
# File lib/protobuf/message/fields.rb, line 85
def extension_fields
  @extension_fields ||= all_fields.select(&:extension?)
end
extension_ranges() click to toggle source
# File lib/protobuf/message/fields.rb, line 89
def extension_ranges
  @extension_ranges ||= []
end
extension_tag?(tag) click to toggle source
# File lib/protobuf/message/fields.rb, line 97
def extension_tag?(tag)
  tag.respond_to?(:to_i) && get_extension_field(tag).present?
end
extensions(range) click to toggle source

Define an extension range.

# File lib/protobuf/message/fields.rb, line 74
def extensions(range)
  extension_ranges << range
end
field_store() click to toggle source
# File lib/protobuf/message/fields.rb, line 101
def field_store
  @field_store ||= {}
end
field_tag?(tag, allow_extension = false) click to toggle source
# File lib/protobuf/message/fields.rb, line 109
def field_tag?(tag, allow_extension = false)
  tag.respond_to?(:to_i) && get_field(tag, allow_extension).present?
end
fields() click to toggle source
# File lib/protobuf/message/fields.rb, line 105
def fields
  @fields ||= all_fields.reject(&:extension?)
end
get_extension_field(name_or_tag) click to toggle source
# File lib/protobuf/message/fields.rb, line 113
def get_extension_field(name_or_tag)
  field = field_store[name_or_tag]
  field if field.try(:extension?) { false }
end
get_field(name_or_tag, allow_extension = false) click to toggle source
# File lib/protobuf/message/fields.rb, line 118
def get_field(name_or_tag, allow_extension = false)
  field = field_store[name_or_tag]

  if field && (allow_extension || !field.extension?)
    field
  else
    nil
  end
end
inherited(subclass) click to toggle source
# File lib/protobuf/message/fields.rb, line 21
        def inherited(subclass)
          inherit_fields!(subclass)
          subclass.const_set("PROTOBUF_MESSAGE_REQUIRED_FIELD_TAGS", subclass.required_field_tags)
          subclass.const_set("PROTOBUF_MESSAGE_GET_FIELD", subclass.field_store)
          subclass.class_eval <<-RUBY, __FILE__, __LINE__
            def _protobuf_message_field
              PROTOBUF_MESSAGE_GET_FIELD
            end

            def _protobuf_message_unset_required_field_tags
              @_protobuf_message_unset_required_field_tags ||= PROTOBUF_MESSAGE_REQUIRED_FIELD_TAGS.dup
            end
          RUBY
        end
map(key_type_class, value_type_class, name, tag, options = {}) click to toggle source

Define a map field.

# File lib/protobuf/message/fields.rb, line 61
def map(key_type_class, value_type_class, name, tag, options = {})
  # manufacture a message that represents the map entry, used for
  # serialization and deserialization
  entry_type = Class.new(::Protobuf::Message) do
    set_option :map_entry, true
    optional key_type_class, :key, 1
    optional value_type_class, :value, 2
  end
  define_field(:repeated, entry_type, name, tag, options)
end
optional(type_class, name, tag, options = {}) click to toggle source

Define an optional field.

# File lib/protobuf/message/fields.rb, line 42
def optional(type_class, name, tag, options = {})
  define_field(:optional, type_class, name, tag, options)
end
raise_if_name_collision(field_name) click to toggle source
# File lib/protobuf/message/fields.rb, line 217
def raise_if_name_collision(field_name)
  if get_field(field_name, true)
    fail DuplicateFieldNameError, %(Field name #{field_name} has already been used in "#{name}".)
  end
end
raise_if_tag_collision(tag, field_name) click to toggle source
# File lib/protobuf/message/fields.rb, line 211
def raise_if_tag_collision(tag, field_name)
  if get_field(tag, true)
    fail TagCollisionError, %(Field number #{tag} has already been used in "#{name}" by field "#{field_name}".)
  end
end
remove_existing_accessors(accessor) click to toggle source
# File lib/protobuf/message/fields.rb, line 198
def remove_existing_accessors(accessor)
  field_store.delete(accessor.to_sym).try(:fully_qualified_name_only!)
  field_store.delete(accessor.to_s)
  ACCESSOR_SUFFIXES.each do |modifier|
    begin
      remove_method("#{accessor}#{modifier}")
    # rubocop: disable Lint/HandleExceptions
    rescue NameError
      # Do not remove the method
    end
  end
end
repeated(type_class, name, tag, options = {}) click to toggle source

Define a repeated field.

# File lib/protobuf/message/fields.rb, line 48
def repeated(type_class, name, tag, options = {})
  define_field(:repeated, type_class, name, tag, options)
end
required(type_class, name, tag, options = {}) click to toggle source

Define a required field.

# File lib/protobuf/message/fields.rb, line 54
def required(type_class, name, tag, options = {})
  required_field_tags << tag
  define_field(:required, type_class, name, tag, options)
end
required_field_tags() click to toggle source
# File lib/protobuf/message/fields.rb, line 93
def required_field_tags
  @required_field_tags ||= []
end

Private Instance Methods

inherit_fields!(subclass) click to toggle source
# File lib/protobuf/message/fields.rb, line 223
def inherit_fields!(subclass)
  instance_variables.each do |iv|
    subclass.instance_variable_set(iv, instance_variable_get(iv))
  end
end