예제 #1
0
static void put_ruby_value(VALUE value,
                           const upb_fielddef *f,
                           VALUE type_class,
                           int depth,
                           upb_sink *sink) {
    upb_selector_t sel = 0;
    if (upb_fielddef_isprimitive(f)) {
        sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
    }

    switch (upb_fielddef_type(f)) {
    case UPB_TYPE_INT32:
        upb_sink_putint32(sink, sel, NUM2INT(value));
        break;
    case UPB_TYPE_INT64:
        upb_sink_putint64(sink, sel, NUM2LL(value));
        break;
    case UPB_TYPE_UINT32:
        upb_sink_putuint32(sink, sel, NUM2UINT(value));
        break;
    case UPB_TYPE_UINT64:
        upb_sink_putuint64(sink, sel, NUM2ULL(value));
        break;
    case UPB_TYPE_FLOAT:
        upb_sink_putfloat(sink, sel, NUM2DBL(value));
        break;
    case UPB_TYPE_DOUBLE:
        upb_sink_putdouble(sink, sel, NUM2DBL(value));
        break;
    case UPB_TYPE_ENUM: {
        if (TYPE(value) == T_SYMBOL) {
            value = rb_funcall(type_class, rb_intern("resolve"), 1, value);
        }
        upb_sink_putint32(sink, sel, NUM2INT(value));
        break;
    }
    case UPB_TYPE_BOOL:
        upb_sink_putbool(sink, sel, value == Qtrue);
        break;
    case UPB_TYPE_STRING:
    case UPB_TYPE_BYTES:
        putstr(value, f, sink);
        break;
    case UPB_TYPE_MESSAGE:
        putsubmsg(value, f, sink, depth);
    }
}
예제 #2
0
static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
                   int depth) {
    upb_sink subsink;
    upb_fieldtype_t type = upb_fielddef_type(f);
    upb_selector_t sel = 0;
    int size;

    if (ary == Qnil) return;

    upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);

    if (upb_fielddef_isprimitive(f)) {
        sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
    }

    size = NUM2INT(RepeatedField_length(ary));
    for (int i = 0; i < size; i++) {
        void* memory = RepeatedField_index_native(ary, i);
        switch (type) {
#define T(upbtypeconst, upbtype, ctype)                         \
  case upbtypeconst:                                            \
    upb_sink_put##upbtype(&subsink, sel, *((ctype *)memory));   \
    break;

            T(UPB_TYPE_FLOAT,  float,  float)
            T(UPB_TYPE_DOUBLE, double, double)
            T(UPB_TYPE_BOOL,   bool,   int8_t)
        case UPB_TYPE_ENUM:
            T(UPB_TYPE_INT32,  int32,  int32_t)
            T(UPB_TYPE_UINT32, uint32, uint32_t)
            T(UPB_TYPE_INT64,  int64,  int64_t)
            T(UPB_TYPE_UINT64, uint64, uint64_t)

        case UPB_TYPE_STRING:
        case UPB_TYPE_BYTES:
            putstr(*((VALUE *)memory), f, &subsink);
            break;
        case UPB_TYPE_MESSAGE:
            putsubmsg(*((VALUE *)memory), f, &subsink, depth);
            break;

#undef T

        }
    }
    upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
}
예제 #3
0
static void putmsg(VALUE msg_rb, const Descriptor* desc,
                   upb_sink *sink, int depth) {
    MessageHeader* msg;
    upb_msg_field_iter i;
    upb_status status;

    upb_sink_startmsg(sink);

    // Protect against cycles (possible because users may freely reassign message
    // and repeated fields) by imposing a maximum recursion depth.
    if (depth > ENCODE_MAX_NESTING) {
        rb_raise(rb_eRuntimeError,
                 "Maximum recursion depth exceeded during encoding.");
    }

    TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);

    for (upb_msg_field_begin(&i, desc->msgdef);
            !upb_msg_field_done(&i);
            upb_msg_field_next(&i)) {
        upb_fielddef *f = upb_msg_iter_field(&i);
        uint32_t offset =
            desc->layout->fields[upb_fielddef_index(f)].offset +
            sizeof(MessageHeader);

        if (upb_fielddef_containingoneof(f)) {
            uint32_t oneof_case_offset =
                desc->layout->fields[upb_fielddef_index(f)].case_offset +
                sizeof(MessageHeader);
            // For a oneof, check that this field is actually present -- skip all the
            // below if not.
            if (DEREF(msg, oneof_case_offset, uint32_t) !=
                    upb_fielddef_number(f)) {
                continue;
            }
            // Otherwise, fall through to the appropriate singular-field handler
            // below.
        }

        if (is_map_field(f)) {
            VALUE map = DEREF(msg, offset, VALUE);
            if (map != Qnil) {
                putmap(map, f, sink, depth);
            }
        } else if (upb_fielddef_isseq(f)) {
            VALUE ary = DEREF(msg, offset, VALUE);
            if (ary != Qnil) {
                putary(ary, f, sink, depth);
            }
        } else if (upb_fielddef_isstring(f)) {
            VALUE str = DEREF(msg, offset, VALUE);
            if (RSTRING_LEN(str) > 0) {
                putstr(str, f, sink);
            }
        } else if (upb_fielddef_issubmsg(f)) {
            putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth);
        } else {
            upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));

#define T(upbtypeconst, upbtype, ctype, default_value)                \
  case upbtypeconst: {                                                \
      ctype value = DEREF(msg, offset, ctype);                        \
      if (value != default_value) {                                   \
        upb_sink_put##upbtype(sink, sel, value);                      \
      }                                                               \
    }                                                                 \
    break;

            switch (upb_fielddef_type(f)) {
                T(UPB_TYPE_FLOAT,  float,  float, 0.0)
                T(UPB_TYPE_DOUBLE, double, double, 0.0)
                T(UPB_TYPE_BOOL,   bool,   uint8_t, 0)
            case UPB_TYPE_ENUM:
                T(UPB_TYPE_INT32,  int32,  int32_t, 0)
                T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
                T(UPB_TYPE_INT64,  int64,  int64_t, 0)
                T(UPB_TYPE_UINT64, uint64, uint64_t, 0)

            case UPB_TYPE_STRING:
            case UPB_TYPE_BYTES:
            case UPB_TYPE_MESSAGE:
                rb_raise(rb_eRuntimeError, "Internal error.");
            }

#undef T

        }
    }

    upb_sink_endmsg(sink, &status);
}
예제 #4
0
파일: handlers.c 프로젝트: YauzZ/upb
bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
                              upb_selector_t *s) {
  switch (type) {
    case UPB_HANDLER_INT32:
    case UPB_HANDLER_INT64:
    case UPB_HANDLER_UINT32:
    case UPB_HANDLER_UINT64:
    case UPB_HANDLER_FLOAT:
    case UPB_HANDLER_DOUBLE:
    case UPB_HANDLER_BOOL:
      if (!upb_fielddef_isprimitive(f) ||
          upb_handlers_getprimitivehandlertype(f) != type)
        return false;
      *s = f->selector_base;
      break;
    case UPB_HANDLER_STRING:
      if (upb_fielddef_isstring(f)) {
        *s = f->selector_base;
      } else if (upb_fielddef_issubmsg(f)) {
        *s = f->selector_base + 3;
      } else {
        return false;
      }
      break;
    case UPB_HANDLER_STARTSTR:
      if (upb_fielddef_isstring(f) || upb_fielddef_issubmsg(f)) {
        *s = f->selector_base + 1;
      } else {
        return false;
      }
      break;
    case UPB_HANDLER_ENDSTR:
      if (upb_fielddef_isstring(f) || upb_fielddef_issubmsg(f)) {
        *s = f->selector_base + 2;
      } else {
        return false;
      }
      break;
    case UPB_HANDLER_STARTSEQ:
      if (!upb_fielddef_isseq(f)) return false;
      *s = f->selector_base - 2;
      break;
    case UPB_HANDLER_ENDSEQ:
      if (!upb_fielddef_isseq(f)) return false;
      *s = f->selector_base - 1;
      break;
    case UPB_HANDLER_STARTSUBMSG:
      if (!upb_fielddef_issubmsg(f)) return false;
      // Selectors for STARTSUBMSG are at the beginning of the table so that the
      // selector can also be used as an index into the "sub" array of
      // subhandlers.  The indexes for the two into these two tables are the
      // same, except that in the handler table the static selectors come first.
      *s = f->index_ + UPB_STATIC_SELECTOR_COUNT;
      break;
    case UPB_HANDLER_ENDSUBMSG:
      if (!upb_fielddef_issubmsg(f)) return false;
      *s = f->selector_base;
      break;
  }
  assert(*s < upb_fielddef_containingtype(f)->selector_count);
  return true;
}