class Google::Protobuf::FieldDescriptor

Attributes

field_def[RW]

Public Class Methods

from_native(field_def, _ = nil) click to toggle source

@param field_def [::FFI::Pointer] FieldDef pointer to be wrapped @param _ [Object] Unused

# File lib/google/protobuf/ffi/field_descriptor.rb, line 35
def from_native(field_def, _ = nil)
  return nil if field_def.nil? or field_def.null?
  file_def = Google::Protobuf::FFI.file_def_by_raw_field_def(field_def)
  descriptor_from_file_def(file_def, field_def)
end
new(*arguments, &block) click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 42
def self.new(*arguments, &block)
  raise "Descriptor objects may not be created from Ruby."
end
new(field_def, descriptor_pool) click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 230
def initialize(field_def, descriptor_pool)
  @field_def = field_def
  @descriptor_pool = descriptor_pool
end
to_native(value, _) click to toggle source

@param value [FieldDescriptor] FieldDescriptor to convert to an FFI native type @param _ [Object] Unused

# File lib/google/protobuf/ffi/field_descriptor.rb, line 25
def to_native(value, _)
  field_def_ptr = value.instance_variable_get(:@field_def)
  warn "Underlying field_def was nil!" if field_def_ptr.nil?
  raise "Underlying field_def was null!" if !field_def_ptr.nil? and field_def_ptr.null?
  field_def_ptr
end

Private Class Methods

private_constructor(field_def, descriptor_pool) click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 235
def self.private_constructor(field_def, descriptor_pool)
  instance = allocate
  instance.send(:initialize, field_def, descriptor_pool)
  instance
end

Public Instance Methods

clear(msg) click to toggle source

@param msg [Google::Protobuf::Message]

# File lib/google/protobuf/ffi/field_descriptor.rb, line 168
def clear(msg)
  if msg.class.descriptor != Google::Protobuf::FFI.get_containing_message_def(self)
    raise TypeError.new "clear method called on wrong message type"
  end
  Google::Protobuf::FFI.clear_message_field msg.instance_variable_get(:@msg), self
  nil
end
default() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 74
def default
  return nil if Google::Protobuf::FFI.is_sub_message(self)
  if Google::Protobuf::FFI.is_repeated(self)
    message_value = Google::Protobuf::FFI::MessageValue.new
  else
    message_value = Google::Protobuf::FFI.get_default(self)
  end
  enum_def = Google::Protobuf::FFI.get_subtype_as_enum(self)
  if enum_def.null?
    convert_upb_to_ruby message_value, c_type
  else
    convert_upb_to_ruby message_value, c_type, enum_def
  end
end
get(msg) click to toggle source

Tests if this field has been set on the argument message.

@param msg [Google::Protobuf::Message] @return [Object] Value of the field on this message. @raise [TypeError] If the field is not defined on this message.

# File lib/google/protobuf/ffi/field_descriptor.rb, line 110
def get(msg)
  if msg.class.descriptor == Google::Protobuf::FFI.get_containing_message_def(self)
    msg.send :get_field, self
  else
    raise TypeError.new "get method called on wrong message type"
  end
end
has?(msg) click to toggle source

Tests if this field has been set on the argument message.

@param msg [Google::Protobuf::Message] @return [Boolean] True iff message has this field set @raise [TypeError] If this field does not exist on the message @raise [ArgumentError] If this field does not track presence

# File lib/google/protobuf/ffi/field_descriptor.rb, line 140
def has?(msg)
  if msg.class.descriptor != Google::Protobuf::FFI.get_containing_message_def(self)
    raise TypeError.new "has method called on wrong message type"
  end
  unless has_presence?
    raise ArgumentError.new "does not track presence"
  end

  Google::Protobuf::FFI.get_message_has msg.instance_variable_get(:@msg), self
end
has_presence?() click to toggle source

Tests if this field tracks presence.

@return [Boolean] True iff this field tracks presence

# File lib/google/protobuf/ffi/field_descriptor.rb, line 155
def has_presence?
  @has_presence ||= Google::Protobuf::FFI.get_has_presence(self)
end
inspect() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 50
def inspect
  "#{self.class.name}: #{name}"
end
is_packed?() click to toggle source

Tests if this is a repeated field that uses packed encoding.

@return [Boolean] True iff this field is packed

# File lib/google/protobuf/ffi/field_descriptor.rb, line 163
def is_packed?
  @is_packed ||= Google::Protobuf::FFI.get_is_packed(self)
end
json_name() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 58
def json_name
  @json_name ||= Google::Protobuf::FFI.get_json_name(self)
end
label() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 70
def label
  @label ||= Google::Protobuf::FFI.get_label(self)
end
map?() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 196
def map?
  @map ||= Google::Protobuf::FFI.is_map self
end
name() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 54
def name
  @name ||= Google::Protobuf::FFI.get_full_name(self)
end
number() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 62
def number
  @number ||= Google::Protobuf::FFI.get_number(self)
end
options() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 217
def options
  @options ||= begin
    size_ptr = ::FFI::MemoryPointer.new(:size_t, 1)
    temporary_arena = Google::Protobuf::FFI.create_arena
    buffer = Google::Protobuf::FFI.field_options(self, size_ptr, temporary_arena)
    opts = Google::Protobuf::FieldOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze)
    opts.clear_features()
    opts.freeze
  end
end
repeated?() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 200
def repeated?
  @repeated ||= Google::Protobuf::FFI.is_repeated self
end
set(message, value) click to toggle source

Sets the value corresponding to this field to the given value on the given message. Raises an exception if message is of the wrong type. Performs the ordinary type-checks for field setting.

@param msg [Google::Protobuf::Message] @param value [Object]

# File lib/google/protobuf/ffi/field_descriptor.rb, line 186
def set(msg, value)
  if msg.class.descriptor != Google::Protobuf::FFI.get_containing_message_def(self)
    raise TypeError.new "set method called on wrong message type"
  end
  unless set_value_on_message value, msg.instance_variable_get(:@msg), msg.instance_variable_get(:@arena)
    raise RuntimeError.new "allocation failed"
  end
  nil
end
sub_message?() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 204
def sub_message?
  @sub_message ||= Google::Protobuf::FFI.is_sub_message self
end
submsg_name() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 89
def submsg_name
  if defined? @submsg_name
    @submsg_name
  else
    @submsg_name = case c_type
      when :enum
        Google::Protobuf::FFI.get_enum_fullname Google::Protobuf::FFI.get_subtype_as_enum self
      when :message
        Google::Protobuf::FFI.get_message_fullname Google::Protobuf::FFI.get_subtype_as_message self
      else
        nil
      end
  end
end
subtype() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 118
def subtype
  if defined? @subtype
    @subtype
  else
    @subtype = case c_type
      when :enum
        Google::Protobuf::FFI.get_subtype_as_enum(self)
      when :message
        Google::Protobuf::FFI.get_subtype_as_message(self)
      else
        nil
      end
  end
end
to_s() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 46
def to_s
  inspect
end
type() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 66
def type
  @type ||= Google::Protobuf::FFI.get_type(self)
end
wrapper?() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 208
def wrapper?
  if defined? @wrapper
    @wrapper
  else
    message_descriptor = Google::Protobuf::FFI.get_subtype_as_message(self)
    @wrapper = message_descriptor.nil? ? false : message_descriptor.send(:wrapper?)
  end
end

Private Instance Methods

c_type() click to toggle source
# File lib/google/protobuf/ffi/field_descriptor.rb, line 299
def c_type
  @c_type ||= Google::Protobuf::FFI.get_c_type(self)
end
real_containing_oneof() click to toggle source

TODO Can this be added to the public API?

# File lib/google/protobuf/ffi/field_descriptor.rb, line 242
def real_containing_oneof
  @real_containing_oneof ||= Google::Protobuf::FFI.real_containing_oneof self
end
set_value_on_message(value, msg, arena, wrap: false) click to toggle source

Sets the field this FieldDescriptor represents to the given value on the given message. @param value [Object] Value to be set @param msg [::FFI::Pointer] Pointer the the upb_Message @param arena [Arena] Arena of the message that owns msg

# File lib/google/protobuf/ffi/field_descriptor.rb, line 254
def set_value_on_message(value, msg, arena, wrap: false)
  message_to_alter = msg
  field_def_to_set = self
  if map?
    raise TypeError.new "Expected map" unless value.is_a? Google::Protobuf::Map
    message_descriptor = subtype

    key_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 1)
    key_field_type = Google::Protobuf::FFI.get_type(key_field_def)
    raise TypeError.new "Map key type does not match field's key type" unless key_field_type == value.send(:key_type)

    value_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 2)
    value_field_type = Google::Protobuf::FFI.get_type(value_field_def)
    raise TypeError.new "Map value type does not match field's value type" unless value_field_type == value.send(:value_type)

    raise TypeError.new "Map value type has wrong message/enum class" unless value_field_def.subtype == value.send(:descriptor)

    arena.fuse(value.send(:arena))
    message_value = Google::Protobuf::FFI::MessageValue.new
    message_value[:map_val] = value.send(:map_ptr)
  elsif repeated?
    raise TypeError.new "Expected repeated field array" unless value.is_a? RepeatedField
    raise TypeError.new "Repeated field array has wrong message/enum class" unless value.send(:type) == type
    arena.fuse(value.send(:arena))
    message_value = Google::Protobuf::FFI::MessageValue.new
    message_value[:array_val] = value.send(:array)
  else
    if value.nil? and (sub_message? or !real_containing_oneof.nil?)
      Google::Protobuf::FFI.clear_message_field message_to_alter, field_def_to_set
      return true
    end
    if wrap
      value_field_def = Google::Protobuf::FFI.get_field_by_number subtype, 1
      type_for_conversion = Google::Protobuf::FFI.get_c_type(value_field_def)
      raise RuntimeError.new "Not expecting to get a msg or enum when unwrapping" if [:enum, :message].include? type_for_conversion
      message_value = convert_ruby_to_upb(value, arena, type_for_conversion, nil)
      message_to_alter = Google::Protobuf::FFI.get_mutable_message(msg, self, arena)[:msg]
      field_def_to_set = value_field_def
    else
      message_value = convert_ruby_to_upb(value, arena, c_type, subtype)
    end
  end
  Google::Protobuf::FFI.set_message_field message_to_alter, field_def_to_set, message_value, arena
end