Example #1
0
/*
 * call-seq:
 *     MessageClass.decode_json(data) => message
 *
 * Decodes the given data (as a string containing bytes in protocol buffers wire
 * format) under the interpretration given by this message class's definition
 * and returns a message object with the corresponding field values.
 */
VALUE Message_decode_json(VALUE klass, VALUE data) {
    VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
    Descriptor* desc = ruby_to_Descriptor(descriptor);
    VALUE msgklass = Descriptor_msgclass(descriptor);
    VALUE msg_rb;
    MessageHeader* msg;

    if (TYPE(data) != T_STRING) {
        rb_raise(rb_eArgError, "Expected string for JSON data.");
    }
    // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
    // convert, because string handlers pass data directly to message string
    // fields.

    msg_rb = rb_class_new_instance(0, NULL, msgklass);
    TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);

    {
        stackenv se;
        upb_sink sink;
        upb_json_parser* parser;
        stackenv_init(&se, "Error occurred during parsing: %s");

        upb_sink_reset(&sink, get_fill_handlers(desc), msg);
        parser = upb_json_parser_create(&se.env, &sink);
        upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
                          upb_json_parser_input(parser));

        stackenv_uninit(&se);
    }

    return msg_rb;
}
Example #2
0
/*
 * call-seq:
 *     MessageClass.decode(data) => message
 *
 * Decodes the given data (as a string containing bytes in protocol buffers wire
 * format) under the interpretration given by this message class's definition
 * and returns a message object with the corresponding field values.
 */
VALUE Message_decode(VALUE klass, VALUE data) {
    VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
    Descriptor* desc = ruby_to_Descriptor(descriptor);
    VALUE msgklass = Descriptor_msgclass(descriptor);
    VALUE msg_rb;
    MessageHeader* msg;

    if (TYPE(data) != T_STRING) {
        rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
    }

    msg_rb = rb_class_new_instance(0, NULL, msgklass);
    TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);

    {
        const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
        const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
        stackenv se;
        upb_sink sink;
        upb_pbdecoder* decoder;
        stackenv_init(&se, "Error occurred during parsing: %s");

        upb_sink_reset(&sink, h, msg);
        decoder = upb_pbdecoder_create(&se.env, method, &sink);
        upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
                          upb_pbdecoder_input(decoder));

        stackenv_uninit(&se);
    }

    return msg_rb;
}
Example #3
0
/*
 * call-seq:
 *     MessageClass.encode_json(msg) => json_string
 *
 * Encodes the given message object into its serialized JSON representation.
 */
VALUE Message_encode_json(VALUE klass, VALUE msg_rb) {
    VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
    Descriptor* desc = ruby_to_Descriptor(descriptor);

    stringsink sink;
    stringsink_init(&sink);

    {
        const upb_handlers* serialize_handlers =
            msgdef_json_serialize_handlers(desc);
        upb_json_printer* printer;
        stackenv se;
        VALUE ret;

        stackenv_init(&se, "Error occurred during encoding: %s");
        printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink);

        putmsg(msg_rb, desc, upb_json_printer_input(printer), 0);

        ret = rb_str_new(sink.ptr, sink.len);

        stackenv_uninit(&se);
        stringsink_uninit(&sink);

        return ret;
    }
}
Example #4
0
// Callback invoked by upb if any error occurs during parsing or serialization.
static bool env_error_func(void* ud, const upb_status* status) {
  stackenv* se = ud;
  // Free the env -- rb_raise will longjmp up the stack past the encode/decode
  // function so it would not otherwise have been freed.
  stackenv_uninit(se);
  rb_raise(rb_eRuntimeError, se->ruby_error_template,
           upb_status_errmsg(status));
  // Never reached: rb_raise() always longjmp()s up the stack, past all of our
  // code, back to Ruby.
  return false;
}
Example #5
0
// Callback invoked by upb if any error occurs during parsing or serialization.
static bool env_error_func(void* ud, const upb_status* status) {
    stackenv* se = ud;
    // Free the env -- rb_raise will longjmp up the stack past the encode/decode
    // function so it would not otherwise have been freed.
    stackenv_uninit(se);

    // TODO(haberman): have a way to verify that this is actually a parse error,
    // instead of just throwing "parse error" unconditionally.
    rb_raise(cParseError, se->ruby_error_template, upb_status_errmsg(status));
    // Never reached: rb_raise() always longjmp()s up the stack, past all of our
    // code, back to Ruby.
    return false;
}
Example #6
0
/*
 * call-seq:
 *     MessageClass.encode_json(msg) => json_string
 *
 * Encodes the given message object into its serialized JSON representation.
 */
VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
  Descriptor* desc = ruby_to_Descriptor(descriptor);
  VALUE msg_rb;
  VALUE preserve_proto_fieldnames = Qfalse;
  stringsink sink;

  if (argc < 1 || argc > 2) {
    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
  }

  msg_rb = argv[0];

  if (argc == 2) {
    VALUE hash_args = argv[1];
    if (TYPE(hash_args) != T_HASH) {
      rb_raise(rb_eArgError, "Expected hash arguments.");
    }
    preserve_proto_fieldnames = rb_hash_lookup2(
        hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse);
  }

  stringsink_init(&sink);

  {
    const upb_handlers* serialize_handlers =
        msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames));
    upb_json_printer* printer;
    stackenv se;
    VALUE ret;

    stackenv_init(&se, "Error occurred during encoding: %s");
    printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink);

    putmsg(msg_rb, desc, upb_json_printer_input(printer), 0);

    ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding());

    stackenv_uninit(&se);
    stringsink_uninit(&sink);

    return ret;
  }
}