예제 #1
0
파일: map.c 프로젝트: Livefyre/protobuf
/*
 * call-seq:
 *     Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
 *     => new map
 *
 * Allocates a new Map container. This constructor may be called with 2, 3, or 4
 * arguments. The first two arguments are always present and are symbols (taking
 * on the same values as field-type symbols in message descriptors) that
 * indicate the type of the map key and value fields.
 *
 * The supported key types are: :int32, :int64, :uint32, :uint64, :bool,
 * :string, :bytes.
 *
 * The supported value types are: :int32, :int64, :uint32, :uint64, :bool,
 * :string, :bytes, :enum, :message.
 *
 * The third argument, value_typeclass, must be present if value_type is :enum
 * or :message. As in RepeatedField#new, this argument must be a message class
 * (for :message) or enum module (for :enum).
 *
 * The last argument, if present, provides initial content for map. Note that
 * this may be an ordinary Ruby hashmap or another Map instance with identical
 * key and value types. Also note that this argument may be present whether or
 * not value_typeclass is present (and it is unambiguously separate from
 * value_typeclass because value_typeclass's presence is strictly determined by
 * value_type). The contents of this initial hashmap or Map instance are
 * shallow-copied into the new Map: the original map is unmodified, but
 * references to underlying objects will be shared if the value type is a
 * message type.
 */
VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
  Map* self = ruby_to_Map(_self);
  int init_value_arg;

  // We take either two args (:key_type, :value_type), three args (:key_type,
  // :value_type, "ValueMessageType"), or four args (the above plus an initial
  // hashmap).
  if (argc < 2 || argc > 4) {
    rb_raise(rb_eArgError, "Map constructor expects 2, 3 or 4 arguments.");
  }

  self->key_type = ruby_to_fieldtype(argv[0]);
  self->value_type = ruby_to_fieldtype(argv[1]);

  // Check that the key type is an allowed type.
  switch (self->key_type) {
    case UPB_TYPE_INT32:
    case UPB_TYPE_INT64:
    case UPB_TYPE_UINT32:
    case UPB_TYPE_UINT64:
    case UPB_TYPE_BOOL:
    case UPB_TYPE_STRING:
    case UPB_TYPE_BYTES:
      // These are OK.
      break;
    default:
      rb_raise(rb_eArgError, "Invalid key type for map.");
  }

  init_value_arg = 2;
  if (needs_typeclass(self->value_type) && argc > 2) {
    self->value_type_class = argv[2];
    validate_type_class(self->value_type, self->value_type_class);
    init_value_arg = 3;
  }

  // Table value type is always UINT64: this ensures enough space to store the
  // native_slot value.
  if (!upb_strtable_init(&self->table, UPB_CTYPE_UINT64)) {
    rb_raise(rb_eRuntimeError, "Could not allocate table.");
  }

  if (argc > init_value_arg) {
    Map_merge_into_self(_self, argv[init_value_arg]);
  }

  return Qnil;
}
예제 #2
0
void RepeatedField_init_args(int argc, VALUE* argv,
                             VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  VALUE ary = Qnil;
  if (argc < 1) {
    rb_raise(rb_eArgError, "Expected at least 1 argument.");
  }
  self->field_type = ruby_to_fieldtype(argv[0]);

  if (self->field_type == UPB_TYPE_MESSAGE ||
      self->field_type == UPB_TYPE_ENUM) {
    if (argc < 2) {
      rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum.");
    }
    self->field_type_class = argv[1];
    if (argc > 2) {
      ary = argv[2];
    }
    validate_type_class(self->field_type, self->field_type_class);
  } else {
    if (argc > 2) {
      rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2.");
    }
    if (argc > 1) {
      ary = argv[1];
    }
  }

  if (ary != Qnil) {
    if (!RB_TYPE_P(ary, T_ARRAY)) {
      rb_raise(rb_eArgError, "Expected array as initialize argument");
    }
    for (int i = 0; i < RARRAY_LEN(ary); i++) {
      RepeatedField_push(_self, rb_ary_entry(ary, i));
    }
  }
}
예제 #3
0
파일: defs.c 프로젝트: Overruler/protobuf
/*
 * call-seq:
 *     FieldDescriptor.type = type
 *
 * Sets this field's type. Cannot be called if field is part of a message type
 * already in a pool.
 */
VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) {
  DEFINE_SELF(FieldDescriptor, self, _self);
  upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
  upb_fielddef_settype(mut_def, ruby_to_fieldtype(type));
  return Qnil;
}