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); } }
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)); }
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); }
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; }