Example #1
0
VALUE layout_get(MessageLayout* layout,
                 const void* storage,
                 const upb_fielddef* field) {
  void* memory = slot_memory(layout, storage, field);
  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);

  bool field_set;
  if (field_contains_hasbit(layout, field)) {
    field_set = slot_is_hasbit_set(layout, storage, field);
  } else {
    field_set = true;
  }

  if (upb_fielddef_containingoneof(field)) {
    if (*oneof_case != upb_fielddef_number(field)) {
      return layout_get_default(field);
    }
    return native_slot_get(upb_fielddef_type(field),
                           field_type_class(field),
                           memory);
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
    return *((VALUE *)memory);
  } else if (!field_set) {
    return layout_get_default(field);
  } else {
    return native_slot_get(upb_fielddef_type(field),
                           field_type_class(field),
                           memory);
  }
}
Example #2
0
void layout_clear(MessageLayout* layout,
                 const void* storage,
                 const upb_fielddef* field) {
  void* memory = slot_memory(layout, storage, field);
  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);

  if (field_contains_hasbit(layout, field)) {
    slot_clear_hasbit(layout, storage, field);
  }

  if (upb_fielddef_containingoneof(field)) {
    memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
    *oneof_case = ONEOF_CASE_NONE;
  } else if (is_map_field(field)) {
    VALUE map = Qnil;

    const upb_fielddef* key_field = map_field_key(field);
    const upb_fielddef* value_field = map_field_value(field);
    VALUE type_class = field_type_class(value_field);

    if (type_class != Qnil) {
      VALUE args[3] = {
        fieldtype_to_ruby(upb_fielddef_type(key_field)),
        fieldtype_to_ruby(upb_fielddef_type(value_field)),
        type_class,
      };
      map = rb_class_new_instance(3, args, cMap);
    } else {
      VALUE args[2] = {
        fieldtype_to_ruby(upb_fielddef_type(key_field)),
        fieldtype_to_ruby(upb_fielddef_type(value_field)),
      };
      map = rb_class_new_instance(2, args, cMap);
    }

    DEREF(memory, VALUE) = map;
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
    VALUE ary = Qnil;

    VALUE type_class = field_type_class(field);

    if (type_class != Qnil) {
      VALUE args[2] = {
        fieldtype_to_ruby(upb_fielddef_type(field)),
        type_class,
      };
      ary = rb_class_new_instance(2, args, cRepeatedField);
    } else {
      VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
      ary = rb_class_new_instance(1, args, cRepeatedField);
    }

    DEREF(memory, VALUE) = ary;
  } else {
    native_slot_set(upb_fielddef_name(field),
                    upb_fielddef_type(field), field_type_class(field),
                    memory, layout_get_default(field));
  }
}
Example #3
0
void layout_init(MessageLayout* layout,
                 void* storage) {
    upb_msg_field_iter it;
    for (upb_msg_field_begin(&it, layout->msgdef);
            !upb_msg_field_done(&it);
            upb_msg_field_next(&it)) {
        const upb_fielddef* field = upb_msg_iter_field(&it);
        void* memory = slot_memory(layout, storage, field);
        uint32_t* oneof_case = slot_oneof_case(layout, storage, field);

        if (upb_fielddef_containingoneof(field)) {
            memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
            *oneof_case = ONEOF_CASE_NONE;
        } else if (is_map_field(field)) {
            VALUE map = Qnil;

            const upb_fielddef* key_field = map_field_key(field);
            const upb_fielddef* value_field = map_field_value(field);
            VALUE type_class = field_type_class(value_field);

            if (type_class != Qnil) {
                VALUE args[3] = {
                    fieldtype_to_ruby(upb_fielddef_type(key_field)),
                    fieldtype_to_ruby(upb_fielddef_type(value_field)),
                    type_class,
                };
                map = rb_class_new_instance(3, args, cMap);
            } else {
                VALUE args[2] = {
                    fieldtype_to_ruby(upb_fielddef_type(key_field)),
                    fieldtype_to_ruby(upb_fielddef_type(value_field)),
                };
                map = rb_class_new_instance(2, args, cMap);
            }

            DEREF(memory, VALUE) = map;
        } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
            VALUE ary = Qnil;

            VALUE type_class = field_type_class(field);

            if (type_class != Qnil) {
                VALUE args[2] = {
                    fieldtype_to_ruby(upb_fielddef_type(field)),
                    type_class,
                };
                ary = rb_class_new_instance(2, args, cRepeatedField);
            } else {
                VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
                ary = rb_class_new_instance(1, args, cRepeatedField);
            }

            DEREF(memory, VALUE) = ary;
        } else {
            native_slot_init(upb_fielddef_type(field), memory);
        }
    }
}
Example #4
0
void layout_set(MessageLayout* layout,
                void* storage,
                const upb_fielddef* field,
                VALUE val) {
  void* memory = slot_memory(layout, storage, field);
  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);

  if (upb_fielddef_containingoneof(field)) {
    if (val == Qnil) {
      // Assigning nil to a oneof field clears the oneof completely.
      *oneof_case = ONEOF_CASE_NONE;
      memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
    } else {
      // The transition between field types for a single oneof (union) slot is
      // somewhat complex because we need to ensure that a GC triggered at any
      // point by a call into the Ruby VM sees a valid state for this field and
      // does not either go off into the weeds (following what it thinks is a
      // VALUE but is actually a different field type) or miss an object (seeing
      // what it thinks is a primitive field but is actually a VALUE for the new
      // field type).
      //
      // In order for the transition to be safe, the oneof case slot must be in
      // sync with the value slot whenever the Ruby VM has been called. Thus, we
      // use native_slot_set_value_and_case(), which ensures that both the value
      // and case number are altered atomically (w.r.t. the Ruby VM).
      native_slot_set_value_and_case(
          upb_fielddef_name(field),
          upb_fielddef_type(field), field_type_class(field),
          memory, val,
          oneof_case, upb_fielddef_number(field));
    }
  } else if (is_map_field(field)) {
    check_map_field_type(val, field);
    DEREF(memory, VALUE) = val;
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
    check_repeated_field_type(val, field);
    DEREF(memory, VALUE) = val;
  } else {
    native_slot_set(upb_fielddef_name(field),
                    upb_fielddef_type(field), field_type_class(field),
                    memory, val);
  }

  if (layout->fields[upb_fielddef_index(field)].hasbit !=
      MESSAGE_FIELD_NO_HASBIT) {
    slot_set_hasbit(layout, storage, field);
  }
}
Example #5
0
VALUE layout_get(MessageLayout* layout,
                 const void* storage,
                 const upb_fielddef* field) {
    void* memory = slot_memory(layout, storage, field);
    uint32_t* oneof_case = slot_oneof_case(layout, storage, field);

    if (upb_fielddef_containingoneof(field)) {
        if (*oneof_case != upb_fielddef_number(field)) {
            return Qnil;
        }
        return native_slot_get(upb_fielddef_type(field),
                               field_type_class(field),
                               memory);
    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
        return *((VALUE *)memory);
    } else {
        return native_slot_get(upb_fielddef_type(field),
                               field_type_class(field),
                               memory);
    }
}