module Gapic::Protobuf

TODO: Describe Protobuf

Public Class Methods

coerce(hash, to: return hash if hash.is_a? to) click to toggle source

Creates an instance of a protobuf message from a hash that may include nested hashes. `google/protobuf` allows for the instantiation of protobuf messages using hashes but does not allow for nested hashes to instantiate nested submessages.

@param hash [Hash, Object] The hash to be converted into a proto message. If an instance of the proto message

class is given, it is returned unchanged.

@param to [Class] The corresponding protobuf message class of the given hash.

@return [Object] An instance of the given message class.

# File lib/gapic/protobuf.rb, line 31
def self.coerce hash, to:
  return hash if hash.is_a? to

  # Sanity check: input must be a Hash
  raise ArgumentError, "Value #{hash} must be a Hash or a #{to.name}" unless hash.is_a? Hash

  hash = coerce_submessages hash, to
  to.new hash
end
time_to_timestamp(time) click to toggle source

Utility for converting a Ruby Time instance to a Google::Protobuf::Timestamp.

@param time [Time] The Time to be converted.

@return [Google::Protobuf::Timestamp] The converted Google::Protobuf::Timestamp.

# File lib/gapic/protobuf.rb, line 146
def self.time_to_timestamp time
  Google::Protobuf::Timestamp.new seconds: time.to_i, nanos: time.nsec
end
timestamp_to_time(timestamp) click to toggle source

Utility for converting a Google::Protobuf::Timestamp instance to a Ruby time.

@param timestamp [Google::Protobuf::Timestamp] The timestamp to be converted.

@return [Time] The converted Time.

# File lib/gapic/protobuf.rb, line 136
def self.timestamp_to_time timestamp
  Time.at timestamp.seconds, timestamp.nanos, :nanosecond
end

Private Class Methods

coerce_array(array, field_descriptor) click to toggle source

Coerces the values of an array to be acceptable by the instantiation method the wrapping message.

@private

@param array [Array<Object>] The values to be coerced. @param field_descriptor [Google::Protobuf::FieldDescriptor] The field descriptor of the values.

@return [Array<Object>] The coerced version of the given values.

# File lib/gapic/protobuf.rb, line 98
def self.coerce_array array, field_descriptor
  raise ArgumentError, "Value #{array} must be an array" unless array.is_a? Array
  array.map do |val|
    coerce_value val, field_descriptor
  end
end
coerce_submessage(val, field_descriptor) click to toggle source

Coerces the value of a field to be acceptable by the instantiation method of the wrapping message.

@private

@param val [Object] The value to be coerced. @param field_descriptor [Google::Protobuf::FieldDescriptor] The field descriptor of the value.

@return [Object] The coerced version of the given value.

# File lib/gapic/protobuf.rb, line 79
def self.coerce_submessage val, field_descriptor
  if (field_descriptor.label == :repeated) && !(map_field? field_descriptor)
    coerce_array val, field_descriptor
  elsif field_descriptor.subtype.msgclass == Google::Protobuf::Timestamp && val.is_a?(Time)
    time_to_timestamp val
  else
    coerce_value val, field_descriptor
  end
end
coerce_submessages(hash, message_class) click to toggle source

Coerces values of the given hash to be acceptable by the instantiation method provided by `google/protobuf`

@private

@param hash [Hash] The hash whose nested hashes will be coerced. @param message_class [Class] The corresponding protobuf message class of the given hash.

@return [Hash] A hash whose nested hashes have been coerced.

# File lib/gapic/protobuf.rb, line 50
def self.coerce_submessages hash, message_class
  return nil if hash.nil?
  coerced = {}
  message_descriptor = message_class.descriptor
  hash.each do |key, val|
    field_descriptor = message_descriptor.lookup key.to_s
    coerced[key] = if field_descriptor && field_descriptor.type == :message
                     coerce_submessage val, field_descriptor
                   elsif field_descriptor && field_descriptor.type == :bytes &&
                         (val.is_a?(IO) || val.is_a?(StringIO))
                     val.binmode.read
                   else
                     # `google/protobuf` should throw an error if no field descriptor is
                     # found. Simply pass through.
                     val
                   end
  end
  coerced
end
coerce_value(val, field_descriptor) click to toggle source

Coerces the value of a field to be acceptable by the instantiation method of the wrapping message.

@private

@param val [Object] The value to be coerced. @param field_descriptor [Google::Protobuf::FieldDescriptor] The field descriptor of the value.

@return [Object] The coerced version of the given value.

# File lib/gapic/protobuf.rb, line 125
def self.coerce_value val, field_descriptor
  return val unless (val.is_a? Hash) && !(map_field? field_descriptor)
  coerce val, to: field_descriptor.subtype.msgclass
end
map_field?(field_descriptor) click to toggle source

Hack to determine if field_descriptor is for a map.

TODO(geigerj): Remove this once protobuf Ruby supports an official way to determine if a FieldDescriptor represents a map. See: github.com/google/protobuf/issues/3425

# File lib/gapic/protobuf.rb, line 111
def self.map_field? field_descriptor
  (field_descriptor.label == :repeated) &&
    (field_descriptor.subtype.name.include? "_MapEntry_")
end