Exemple #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);
  }
}
Exemple #2
0
upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
  upb_fielddef *newf = upb_fielddef_new(owner);
  if (!newf) return NULL;
  upb_fielddef_settype(newf, upb_fielddef_type(f));
  upb_fielddef_setlabel(newf, upb_fielddef_label(f));
  upb_fielddef_setnumber(newf, upb_fielddef_number(f), NULL);
  upb_fielddef_setname(newf, upb_fielddef_name(f), NULL);
  if (f->default_is_string) {
    str_t *s = upb_value_getptr(upb_fielddef_default(f));
    upb_fielddef_setdefaultstr(newf, s->str, s->len, NULL);
  } else {
    upb_fielddef_setdefault(newf, upb_fielddef_default(f));
  }

  const char *srcname;
  if (f->subdef_is_symbolic) {
    srcname = f->sub.name;  // Might be NULL.
  } else {
    srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL;
  }
  if (srcname) {
    char *newname = malloc(strlen(f->sub.def->fullname) + 2);
    if (!newname) {
      upb_fielddef_unref(newf, owner);
      return NULL;
    }
    strcpy(newname, ".");
    strcat(newname, f->sub.def->fullname);
    upb_fielddef_setsubdefname(newf, newname, NULL);
    free(newname);
  }

  return newf;
}
Exemple #3
0
static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
  RepeatedField* self;
  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);

  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
      RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
    rb_raise(cTypeError, "Expected repeated field array");
  }

  self = ruby_to_RepeatedField(val);
  if (self->field_type != upb_fielddef_type(field)) {
    rb_raise(cTypeError, "Repeated field array has wrong element type");
  }

  if (self->field_type == UPB_TYPE_MESSAGE) {
    if (self->field_type_class !=
        Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
      rb_raise(cTypeError,
               "Repeated field array has wrong message class");
    }
  }


  if (self->field_type == UPB_TYPE_ENUM) {
    if (self->field_type_class !=
        EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
      rb_raise(cTypeError,
               "Repeated field array has wrong enum class");
    }
  }
}
Exemple #4
0
void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
  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* to_memory = slot_memory(layout, to, field);
    uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
    void* from_memory = slot_memory(layout, from, field);
    uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);

    if (upb_fielddef_containingoneof(field)) {
      if (*from_oneof_case == upb_fielddef_number(field)) {
        *to_oneof_case = *from_oneof_case;
        native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
      }
    } else if (is_map_field(field)) {
      DEREF(to_memory, VALUE) =
          Map_deep_copy(DEREF(from_memory, VALUE));
    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      DEREF(to_memory, VALUE) =
          RepeatedField_deep_copy(DEREF(from_memory, VALUE));
    } else {
      if (field_contains_hasbit(layout, field)) {
        if (!slot_is_hasbit_set(layout, from, field)) continue;
        slot_set_hasbit(layout, to, field);
      }

      native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
    }
  }
}
Exemple #5
0
static PyObject *PyUpb_FieldDef_getattro(PyObject *obj, PyObject *attr_name) {
  upb_fielddef *f = Check_FieldDef(obj, NULL);
  if (!upb_fielddef_ismutable(f)) {
    PyErr_SetString(PyExc_TypeError, "fielddef is not mutable.");
    return NULL;
  }
  const char *name = PyString_AsString(attr_name);
  if (streql(name, "name")) {
    const char *name = upb_fielddef_name(f);
    return name == NULL ? Py_None : PyString_FromString(name);
  } else if (streql(name, "number")) {
    uint32_t num = upb_fielddef_number(f);
    return num == 0 ? Py_None : PyInt_FromLong(num);
  } else if (streql(name, "type")) {
    uint8_t type = upb_fielddef_type(f);
    return type == 0 ? Py_None : PyInt_FromLong(type);
  } else if (streql(name, "label")) {
    return PyInt_FromLong(upb_fielddef_label(f));
  } else if (streql(name, "type_name")) {
    const char *name = upb_fielddef_typename(f);
    return name == NULL ? Py_None : PyString_FromString(name);
  } else if (streql(name, "subdef")) {
    // NYI;
    return NULL;
  } else if (streql(name, "msgdef")) {
    // NYI;
    return NULL;
  } else {
    return PyUpb_Error("Invalid fielddef member.");
  }
}
Exemple #6
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));
  }
}
Exemple #7
0
int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
  MessageHeader* self;
  char *name;
  const upb_fielddef* f;
  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);

  if (TYPE(key) == T_STRING) {
    name = RSTRING_PTR(key);
  } else if (TYPE(key) == T_SYMBOL) {
    name = RSTRING_PTR(rb_id2str(SYM2ID(key)));
  } else {
    rb_raise(rb_eArgError,
             "Expected string or symbols as hash keys when initializing proto from hash.");
  }

  f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
  if (f == NULL) {
    rb_raise(rb_eArgError,
             "Unknown field name '%s' in initialization map entry.", name);
  }

  if (TYPE(val) == T_NIL) {
    return 0;
  }

  if (is_map_field(f)) {
    VALUE map;

    if (TYPE(val) != T_HASH) {
      rb_raise(rb_eArgError,
               "Expected Hash object as initializer value for map field '%s'.", name);
    }
    map = layout_get(self->descriptor->layout, Message_data(self), f);
    Map_merge_into_self(map, val);
  } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
    VALUE ary;

    if (TYPE(val) != T_ARRAY) {
      rb_raise(rb_eArgError,
               "Expected array as initializer value for repeated field '%s'.", name);
    }
    ary = layout_get(self->descriptor->layout, Message_data(self), f);
    for (int i = 0; i < RARRAY_LEN(val); i++) {
      VALUE entry = rb_ary_entry(val, i);
      if (TYPE(entry) == T_HASH && upb_fielddef_issubmsg(f)) {
        entry = create_submsg_from_hash(f, entry);
      }

      RepeatedField_push(ary, entry);
    }
  } else {
    if (TYPE(val) == T_HASH && upb_fielddef_issubmsg(f)) {
      val = create_submsg_from_hash(f, val);
    }

    layout_set(self->descriptor->layout, Message_data(self), f, val);
  }
  return 0;
}
Exemple #8
0
bool is_map_field(const upb_fielddef* field) {
    if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
            upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
        return false;
    }
    const upb_msgdef* subdef = upb_fielddef_msgsubdef(field);
    return upb_msgdef_mapentry(subdef);
}
Exemple #9
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);
        }
    }
}
Exemple #10
0
const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) {
  const upb_msgdef* subdef;
  if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
      upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
    return NULL;
  }
  subdef = upb_fielddef_msgsubdef(field);
  return upb_msgdef_mapentry(subdef) ? subdef : NULL;
}
Exemple #11
0
static void validate_msgdef(const upb_msgdef* msgdef) {
  // Verify that no required fields exist. proto3 does not support these.
  upb_msg_iter it;
  for (upb_msg_begin(&it, msgdef); !upb_msg_done(&it); upb_msg_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
      rb_raise(rb_eTypeError, "Required fields are unsupported in proto3.");
    }
  }
}
Exemple #12
0
/*
 * call-seq:
 *     FieldDescriptor.label => label
 *
 * Returns this field's label (i.e., plurality), as a Ruby symbol.
 *
 * Valid field labels are:
 *     :optional, :repeated
 */
VALUE FieldDescriptor_label(VALUE _self) {
  DEFINE_SELF(FieldDescriptor, self, _self);
  switch (upb_fielddef_label(self->fielddef)) {
#define CONVERT(upb, ruby)                                           \
    case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby ));

    CONVERT(OPTIONAL, optional);
    CONVERT(REQUIRED, required);
    CONVERT(REPEATED, repeated);

#undef CONVERT
  }

  return Qnil;
}
Exemple #13
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);
  }
}
Exemple #14
0
/*
 * call-seq:
 *     Message.to_h => {}
 *
 * Returns the message as a Ruby Hash object, with keys as symbols.
 */
VALUE Message_to_h(VALUE _self) {
  MessageHeader* self;
  VALUE hash;
  upb_msg_field_iter it;
  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);

  hash = rb_hash_new();

  for (upb_msg_field_begin(&it, self->descriptor->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);

    // For proto2, do not include fields which are not set.
    if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
	field_contains_hasbit(self->descriptor->layout, field) &&
	!layout_has(self->descriptor->layout, Message_data(self), field)) {
      continue;
    }

    VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self),
                                 field);
    VALUE msg_key   = ID2SYM(rb_intern(upb_fielddef_name(field)));
    if (is_map_field(field)) {
      msg_value = Map_to_h(msg_value);
    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      msg_value = RepeatedField_to_ary(msg_value);
      if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
          RARRAY_LEN(msg_value) == 0) {
        continue;
      }

      if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
        for (int i = 0; i < RARRAY_LEN(msg_value); i++) {
          VALUE elem = rb_ary_entry(msg_value, i);
          rb_ary_store(msg_value, i, Message_to_h(elem));
        }
      }

    } else if (msg_value != Qnil &&
               upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
      msg_value = Message_to_h(msg_value);
    }
    rb_hash_aset(hash, msg_key, msg_value);
  }
  return hash;
}
Exemple #15
0
int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
  MessageHeader* self;
  VALUE method_str;
  char* name;
  const upb_fielddef* f;
  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);

  if (!SYMBOL_P(key)) {
    rb_raise(rb_eArgError,
             "Expected symbols as hash keys in initialization map.");
  }

  method_str = rb_id2str(SYM2ID(key));
  name = RSTRING_PTR(method_str);
  f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
  if (f == NULL) {
    rb_raise(rb_eArgError,
             "Unknown field name '%s' in initialization map entry.", name);
  }

  if (is_map_field(f)) {
    VALUE map;

    if (TYPE(val) != T_HASH) {
      rb_raise(rb_eArgError,
               "Expected Hash object as initializer value for map field '%s'.", name);
    }
    map = layout_get(self->descriptor->layout, Message_data(self), f);
    Map_merge_into_self(map, val);
  } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
    VALUE ary;

    if (TYPE(val) != T_ARRAY) {
      rb_raise(rb_eArgError,
               "Expected array as initializer value for repeated field '%s'.", name);
    }
    ary = layout_get(self->descriptor->layout, Message_data(self), f);
    for (int i = 0; i < RARRAY_LEN(val); i++) {
      RepeatedField_push(ary, rb_ary_entry(val, i));
    }
  } else {
    layout_set(self->descriptor->layout, Message_data(self), f, val);
  }
  return 0;
}
Exemple #16
0
VALUE Message_to_h(VALUE _self) {
  MessageHeader* self;
  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);

  VALUE hash = rb_hash_new();

  upb_msg_field_iter it;
  for (upb_msg_field_begin(&it, self->descriptor->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self), field);
    VALUE msg_key   = ID2SYM(rb_intern(upb_fielddef_name(field)));
    if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      msg_value = RepeatedField_to_ary(msg_value);
    }
    rb_hash_aset(hash, msg_key, msg_value);
  }
  return hash;
}
Exemple #17
0
void layout_mark(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)) {
      if (*oneof_case == upb_fielddef_number(field)) {
        native_slot_mark(upb_fielddef_type(field), memory);
      }
    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      rb_gc_mark(DEREF(memory, VALUE));
    } else {
      native_slot_mark(upb_fielddef_type(field), memory);
    }
  }
}
Exemple #18
0
VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
  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* msg1_memory = slot_memory(layout, msg1, field);
    uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
    void* msg2_memory = slot_memory(layout, msg2, field);
    uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);

    if (upb_fielddef_containingoneof(field)) {
      if (*msg1_oneof_case != *msg2_oneof_case ||
          (*msg1_oneof_case == upb_fielddef_number(field) &&
           !native_slot_eq(upb_fielddef_type(field),
                           msg1_memory,
                           msg2_memory))) {
        return Qfalse;
      }
    } else if (is_map_field(field)) {
      if (!Map_eq(DEREF(msg1_memory, VALUE),
                  DEREF(msg2_memory, VALUE))) {
        return Qfalse;
      }
    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      if (!RepeatedField_eq(DEREF(msg1_memory, VALUE),
                            DEREF(msg2_memory, VALUE))) {
        return Qfalse;
      }
    } else {
      if (slot_is_hasbit_set(layout, msg1, field) !=
	  slot_is_hasbit_set(layout, msg2, field) ||
          !native_slot_eq(upb_fielddef_type(field),
			  msg1_memory, msg2_memory)) {
        return Qfalse;
      }
    }
  }
  return Qtrue;
}
Exemple #19
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);
    }
}
Exemple #20
0
upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
  upb_fielddef *newf = upb_fielddef_new(owner);
  if (!newf) return NULL;
  upb_fielddef_settype(newf, upb_fielddef_type(f));
  upb_fielddef_setlabel(newf, upb_fielddef_label(f));
  upb_fielddef_setnumber(newf, upb_fielddef_number(f));
  upb_fielddef_setname(newf, upb_fielddef_name(f));
  if (f->default_is_string) {
    upb_byteregion *r = upb_value_getbyteregion(upb_fielddef_default(f));
    size_t len;
    const char *ptr = upb_byteregion_getptr(r, 0, &len);
    assert(len == upb_byteregion_len(r));
    upb_fielddef_setdefaultstr(newf, ptr, len);
  } else {
    upb_fielddef_setdefault(newf, upb_fielddef_default(f));
  }

  const char *srcname;
  if (f->subdef_is_symbolic) {
    srcname = f->sub.name;  // Might be NULL.
  } else {
    srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL;
  }
  if (srcname) {
    char *newname = malloc(strlen(f->sub.def->fullname) + 2);
    if (!newname) {
      upb_fielddef_unref(newf, owner);
      return NULL;
    }
    strcpy(newname, ".");
    strcat(newname, f->sub.def->fullname);
    upb_fielddef_setsubdefname(newf, newname);
    free(newname);
  }

  return newf;
}
Exemple #21
0
bool upb_fielddef_isseq(const upb_fielddef *f) {
  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
}
Exemple #22
0
MessageLayout* create_layout(const upb_msgdef* msgdef) {
  MessageLayout* layout = ALLOC(MessageLayout);
  int nfields = upb_msgdef_numfields(msgdef);
  upb_msg_field_iter it;
  upb_msg_oneof_iter oit;
  size_t off = 0;

  layout->fields = ALLOC_N(MessageField, nfields);

  size_t hasbit = 0;
  for (upb_msg_field_begin(&it, msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    if (upb_fielddef_haspresence(field)) {
      layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
    } else {
      layout->fields[upb_fielddef_index(field)].hasbit =
	  MESSAGE_FIELD_NO_HASBIT;
    }
  }

  if (hasbit != 0) {
    off += (hasbit + 8 - 1) / 8;
  }

  for (upb_msg_field_begin(&it, msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    size_t field_size;

    if (upb_fielddef_containingoneof(field)) {
      // Oneofs are handled separately below.
      continue;
    }

    // Allocate |field_size| bytes for this field in the layout.
    field_size = 0;
    if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      field_size = sizeof(VALUE);
    } else {
      field_size = native_slot_size(upb_fielddef_type(field));
    }
    // Align current offset up to |size| granularity.
    off = align_up_to(off, field_size);
    layout->fields[upb_fielddef_index(field)].offset = off;
    layout->fields[upb_fielddef_index(field)].case_offset =
        MESSAGE_FIELD_NO_CASE;
    off += field_size;
  }

  // Handle oneofs now -- we iterate over oneofs specifically and allocate only
  // one slot per oneof.
  //
  // We assign all value slots first, then pack the 'case' fields at the end,
  // since in the common case (modern 64-bit platform) these are 8 bytes and 4
  // bytes respectively and we want to avoid alignment overhead.
  //
  // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
  // space for oneof cases is conceptually as wide as field tag numbers. In
  // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
  // members (8 or 16 bits respectively), so conceivably we could assign
  // consecutive case numbers and then pick a smaller oneof case slot size, but
  // the complexity to implement this indirection is probably not worthwhile.
  for (upb_msg_oneof_begin(&oit, msgdef);
       !upb_msg_oneof_done(&oit);
       upb_msg_oneof_next(&oit)) {
    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
    upb_oneof_iter fit;

    // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
    // all fields.
    size_t field_size = NATIVE_SLOT_MAX_SIZE;
    // Align the offset.
    off = align_up_to(off, field_size);
    // Assign all fields in the oneof this same offset.
    for (upb_oneof_begin(&fit, oneof);
         !upb_oneof_done(&fit);
         upb_oneof_next(&fit)) {
      const upb_fielddef* field = upb_oneof_iter_field(&fit);
      layout->fields[upb_fielddef_index(field)].offset = off;
    }
    off += field_size;
  }

  // Now the case fields.
  for (upb_msg_oneof_begin(&oit, msgdef);
       !upb_msg_oneof_done(&oit);
       upb_msg_oneof_next(&oit)) {
    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
    upb_oneof_iter fit;

    size_t field_size = sizeof(uint32_t);
    // Align the offset.
    off = (off + field_size - 1) & ~(field_size - 1);
    // Assign all fields in the oneof this same offset.
    for (upb_oneof_begin(&fit, oneof);
         !upb_oneof_done(&fit);
         upb_oneof_next(&fit)) {
      const upb_fielddef* field = upb_oneof_iter_field(&fit);
      layout->fields[upb_fielddef_index(field)].case_offset = off;
    }
    off += field_size;
  }

  layout->size = off;

  layout->msgdef = msgdef;
  upb_msgdef_ref(layout->msgdef, &layout->msgdef);

  return layout;
}
Exemple #23
0
static bool upb_msglayout_init(const upb_msgdef *m,
                               upb_msglayout *l,
                               upb_msgfactory *factory) {
  upb_msg_field_iter it;
  upb_msg_oneof_iter oit;
  size_t hasbit;
  size_t submsg_count = 0;
  const upb_msglayout **submsgs;
  upb_msglayout_field *fields;

  for (upb_msg_field_begin(&it, m);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* f = upb_msg_iter_field(&it);
    if (upb_fielddef_issubmsg(f)) {
      submsg_count++;
    }
  }

  memset(l, 0, sizeof(*l));

  fields = upb_gmalloc(upb_msgdef_numfields(m) * sizeof(*fields));
  submsgs = upb_gmalloc(submsg_count * sizeof(*submsgs));

  if ((!fields && upb_msgdef_numfields(m)) ||
      (!submsgs && submsg_count)) {
    /* OOM. */
    upb_gfree(fields);
    upb_gfree(submsgs);
    return false;
  }

  l->field_count = upb_msgdef_numfields(m);
  l->fields = fields;
  l->submsgs = submsgs;

  /* Allocate data offsets in three stages:
   *
   * 1. hasbits.
   * 2. regular fields.
   * 3. oneof fields.
   *
   * OPT: There is a lot of room for optimization here to minimize the size.
   */

  /* Allocate hasbits and set basic field attributes. */
  submsg_count = 0;
  for (upb_msg_field_begin(&it, m), hasbit = 0;
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* f = upb_msg_iter_field(&it);
    upb_msglayout_field *field = &fields[upb_fielddef_index(f)];

    field->number = upb_fielddef_number(f);
    field->descriptortype = upb_fielddef_descriptortype(f);
    field->label = upb_fielddef_label(f);

    if (upb_fielddef_issubmsg(f)) {
      const upb_msglayout *sub_layout =
          upb_msgfactory_getlayout(factory, upb_fielddef_msgsubdef(f));
      field->submsg_index = submsg_count++;
      submsgs[field->submsg_index] = sub_layout;
    }

    if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) {
      field->presence = (hasbit++);
    } else {
      field->presence = 0;
    }
  }

  /* Account for space used by hasbits. */
  l->size = div_round_up(hasbit, 8);

  /* Allocate non-oneof fields. */
  for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* f = upb_msg_iter_field(&it);
    size_t field_size = upb_msg_fielddefsize(f);
    size_t index = upb_fielddef_index(f);

    if (upb_fielddef_containingoneof(f)) {
      /* Oneofs are handled separately below. */
      continue;
    }

    fields[index].offset = upb_msglayout_place(l, field_size);
  }

  /* Allocate oneof fields.  Each oneof field consists of a uint32 for the case
   * and space for the actual data. */
  for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
       upb_msg_oneof_next(&oit)) {
    const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
    upb_oneof_iter fit;

    size_t case_size = sizeof(uint32_t);  /* Could potentially optimize this. */
    size_t field_size = 0;
    uint32_t case_offset;
    uint32_t data_offset;

    /* Calculate field size: the max of all field sizes. */
    for (upb_oneof_begin(&fit, o);
         !upb_oneof_done(&fit);
         upb_oneof_next(&fit)) {
      const upb_fielddef* f = upb_oneof_iter_field(&fit);
      field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
    }

    /* Align and allocate case offset. */
    case_offset = upb_msglayout_place(l, case_size);
    data_offset = upb_msglayout_place(l, field_size);

    for (upb_oneof_begin(&fit, o);
         !upb_oneof_done(&fit);
         upb_oneof_next(&fit)) {
      const upb_fielddef* f = upb_oneof_iter_field(&fit);
      fields[upb_fielddef_index(f)].offset = data_offset;
      fields[upb_fielddef_index(f)].presence = ~case_offset;
    }
  }

  /* Size of the entire structure should be a multiple of its greatest
   * alignment.  TODO: track overall alignment for real? */
  l->size = align_up(l->size, 8);

  return true;
}