msgpack-rpc: Always use arrays when sending events or calls

This is required by the msgpack-RPC specification. Also, the
send_call/send_event functions were refactored to accept a variable number of
arguments
This commit is contained in:
Thiago de Arruda 2014-08-28 17:01:58 -03:00
parent aa23d2f835
commit a66d2d1538
6 changed files with 72 additions and 44 deletions

View File

@ -6493,8 +6493,8 @@ static struct fst {
{"searchpair", 3, 7, f_searchpair}, {"searchpair", 3, 7, f_searchpair},
{"searchpairpos", 3, 7, f_searchpairpos}, {"searchpairpos", 3, 7, f_searchpairpos},
{"searchpos", 1, 4, f_searchpos}, {"searchpos", 1, 4, f_searchpos},
{"send_call", 3, 3, f_send_call}, {"send_call", 2, 64, f_send_call},
{"send_event", 3, 3, f_send_event}, {"send_event", 2, 64, f_send_event},
{"setbufvar", 3, 3, f_setbufvar}, {"setbufvar", 3, 3, f_setbufvar},
{"setcmdpos", 1, 1, f_setcmdpos}, {"setcmdpos", 1, 1, f_setcmdpos},
{"setline", 2, 2, f_setline}, {"setline", 2, 2, f_setline},
@ -12632,13 +12632,19 @@ static void f_send_call(typval_T *argvars, typval_T *rettv)
return; return;
} }
Array args = ARRAY_DICT_INIT;
for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) {
ADD(args, vim_to_object(tv));
}
bool errored; bool errored;
Object result; Object result;
if (!channel_send_call((uint64_t)argvars[0].vval.v_number, if (!channel_send_call((uint64_t)argvars[0].vval.v_number,
(char *)argvars[1].vval.v_string, (char *)argvars[1].vval.v_string,
vim_to_object(&argvars[2]), args,
&result, &result,
&errored)) { &errored)) {
EMSG2(_(e_invarg2), "Channel doesn't exist"); EMSG2(_(e_invarg2), "Channel doesn't exist");
return; return;
} }
@ -12673,9 +12679,15 @@ static void f_send_event(typval_T *argvars, typval_T *rettv)
return; return;
} }
Array args = ARRAY_DICT_INIT;
for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) {
ADD(args, vim_to_object(tv));
}
if (!channel_send_event((uint64_t)argvars[0].vval.v_number, if (!channel_send_event((uint64_t)argvars[0].vval.v_number,
(char *)argvars[1].vval.v_string, (char *)argvars[1].vval.v_string,
vim_to_object(&argvars[2]))) { args)) {
EMSG2(_(e_invarg2), "Channel doesn't exist"); EMSG2(_(e_invarg2), "Channel doesn't exist");
return; return;
} }
@ -19149,7 +19161,9 @@ static void apply_job_autocmds(Job *job, char *name, char *type, char *str)
static void script_host_eval(char *method, typval_T *argvars, typval_T *rettv) static void script_host_eval(char *method, typval_T *argvars, typval_T *rettv)
{ {
Object result = provider_call(method, vim_to_object(argvars)); Array args = ARRAY_DICT_INIT;
ADD(args, vim_to_object(argvars));
Object result = provider_call(method, args);
if (result.type == kObjectTypeNil) { if (result.type == kObjectTypeNil) {
return; return;

View File

@ -3251,8 +3251,9 @@ static void script_host_execute(char *method, exarg_T *eap)
char *script = (char *)script_get(eap, eap->arg); char *script = (char *)script_get(eap, eap->arg);
if (!eap->skip) { if (!eap->skip) {
String str = cstr_to_string(script ? script : (char *)eap->arg); Array args = ARRAY_DICT_INIT;
Object result = provider_call(method, STRING_OBJ(str)); ADD(args, STRING_OBJ(cstr_to_string(script ? script : (char *)eap->arg)));
Object result = provider_call(method, args);
// We don't care about the result, so free it just in case a bad provider // We don't care about the result, so free it just in case a bad provider
// returned something // returned something
msgpack_rpc_free_object(result); msgpack_rpc_free_object(result);
@ -3266,18 +3267,19 @@ static void script_host_execute_file(char *method, exarg_T *eap)
char buffer[MAXPATHL]; char buffer[MAXPATHL];
vim_FullName(eap->arg, (uint8_t *)buffer, sizeof(buffer), false); vim_FullName(eap->arg, (uint8_t *)buffer, sizeof(buffer), false);
String file = cstr_to_string(buffer); Array args = ARRAY_DICT_INIT;
Object result = provider_call(method, STRING_OBJ(file)); ADD(args, STRING_OBJ(cstr_to_string(buffer)));
Object result = provider_call(method, args);
msgpack_rpc_free_object(result); msgpack_rpc_free_object(result);
} }
static void script_host_do_range(char *method, exarg_T *eap) static void script_host_do_range(char *method, exarg_T *eap)
{ {
Array arg = {0, 0, 0}; Array args = ARRAY_DICT_INIT;
ADD(arg, INTEGER_OBJ(eap->line1)); ADD(args, INTEGER_OBJ(eap->line1));
ADD(arg, INTEGER_OBJ(eap->line2)); ADD(args, INTEGER_OBJ(eap->line2));
ADD(arg, STRING_OBJ(cstr_to_string((char *)eap->arg))); ADD(args, STRING_OBJ(cstr_to_string((char *)eap->arg)));
Object result = provider_call(method, ARRAY_OBJ(arg)); Object result = provider_call(method, args);
msgpack_rpc_free_object(result); msgpack_rpc_free_object(result);
} }

View File

@ -5232,7 +5232,8 @@ static void get_clipboard(int name)
struct yankreg *reg = &y_regs[CLIP_REGISTER]; struct yankreg *reg = &y_regs[CLIP_REGISTER];
free_register(reg); free_register(reg);
Object result = provider_call("clipboard_get", NIL); Array args = ARRAY_DICT_INIT;
Object result = provider_call("clipboard_get", args);
if (result.type != kObjectTypeArray) { if (result.type != kObjectTypeArray) {
goto err; goto err;
@ -5278,12 +5279,15 @@ static void set_clipboard(int name)
copy_register(reg, &y_regs[0]); copy_register(reg, &y_regs[0]);
} }
Array lines = {0, 0, 0}; Array lines = ARRAY_DICT_INIT;
for (int i = 0; i < reg->y_size; i++) { for (int i = 0; i < reg->y_size; i++) {
ADD(lines, STRING_OBJ(cstr_to_string((char *)reg->y_array[i]))); ADD(lines, STRING_OBJ(cstr_to_string((char *)reg->y_array[i])));
} }
Object result = provider_call("clipboard_set", ARRAY_OBJ(lines)); Array args = ARRAY_DICT_INIT;
ADD(args, ARRAY_OBJ(lines));
Object result = provider_call("clipboard_set", args);
msgpack_rpc_free_object(result); msgpack_rpc_free_object(result);
} }

View File

@ -143,40 +143,48 @@ bool channel_exists(uint64_t id)
&& channel->enabled; && channel->enabled;
} }
/// Sends event/data to channel /// Sends event/arguments to channel
/// ///
/// @param id The channel id. If 0, the event will be sent to all /// @param id The channel id. If 0, the event will be sent to all
/// channels that have subscribed to the event type /// channels that have subscribed to the event type
/// @param name The event name, an arbitrary string /// @param name The event name, an arbitrary string
/// @param arg The event arg /// @param args Array with event arguments
/// @return True if the data was sent successfully, false otherwise. /// @return True if the event was sent successfully, false otherwise.
bool channel_send_event(uint64_t id, char *name, Object arg) bool channel_send_event(uint64_t id, char *name, Array args)
{ {
Channel *channel = NULL; Channel *channel = NULL;
if (id > 0) { if (id > 0) {
if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) { if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {
msgpack_rpc_free_object(arg); msgpack_rpc_free_array(args);
return false; return false;
} }
send_event(channel, name, arg); send_event(channel, name, args);
} else { } else {
broadcast_event(name, arg); broadcast_event(name, args);
} }
return true; return true;
} }
/// Sends a method call to a channel
///
/// @param id The channel id
/// @param name The method name, an arbitrary string
/// @param args Array with method arguments
/// @param[out] result Pointer to return value received from the channel
/// @param[out] error True if the return value is an error
/// @return True if the call was sent successfully, false otherwise.
bool channel_send_call(uint64_t id, bool channel_send_call(uint64_t id,
char *name, char *name,
Object arg, Array args,
Object *result, Object *result,
bool *errored) bool *errored)
{ {
Channel *channel = NULL; Channel *channel = NULL;
if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) { if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {
msgpack_rpc_free_object(arg); msgpack_rpc_free_array(args);
return false; return false;
} }
@ -190,13 +198,13 @@ bool channel_send_call(uint64_t id,
"while processing a RPC call", "while processing a RPC call",
channel->id); channel->id);
*result = STRING_OBJ(cstr_to_string(buf)); *result = STRING_OBJ(cstr_to_string(buf));
msgpack_rpc_free_object(arg); msgpack_rpc_free_array(args);
return false; return false;
} }
uint64_t request_id = channel->next_request_id++; uint64_t request_id = channel->next_request_id++;
// Send the msgpack-rpc request // Send the msgpack-rpc request
send_request(channel, request_id, name, arg); send_request(channel, request_id, name, args);
EventSource channel_source = channel->is_job EventSource channel_source = channel->is_job
? job_event_source(channel->data.job) ? job_event_source(channel->data.job)
@ -415,21 +423,21 @@ static void send_error(Channel *channel, uint64_t id, char *err)
static void send_request(Channel *channel, static void send_request(Channel *channel,
uint64_t id, uint64_t id,
char *name, char *name,
Object arg) Array args)
{ {
String method = {.size = strlen(name), .data = name}; String method = {.size = strlen(name), .data = name};
channel_write(channel, serialize_request(id, method, arg, &out_buffer, 1)); channel_write(channel, serialize_request(id, method, args, &out_buffer, 1));
} }
static void send_event(Channel *channel, static void send_event(Channel *channel,
char *name, char *name,
Object arg) Array args)
{ {
String method = {.size = strlen(name), .data = name}; String method = {.size = strlen(name), .data = name};
channel_write(channel, serialize_request(0, method, arg, &out_buffer, 1)); channel_write(channel, serialize_request(0, method, args, &out_buffer, 1));
} }
static void broadcast_event(char *name, Object arg) static void broadcast_event(char *name, Array args)
{ {
kvec_t(Channel *) subscribed; kvec_t(Channel *) subscribed;
kv_init(subscribed); kv_init(subscribed);
@ -442,14 +450,14 @@ static void broadcast_event(char *name, Object arg)
}); });
if (!kv_size(subscribed)) { if (!kv_size(subscribed)) {
msgpack_rpc_free_object(arg); msgpack_rpc_free_array(args);
goto end; goto end;
} }
String method = {.size = strlen(name), .data = name}; String method = {.size = strlen(name), .data = name};
WBuffer *buffer = serialize_request(0, WBuffer *buffer = serialize_request(0,
method, method,
arg, args,
&out_buffer, &out_buffer,
kv_size(subscribed)); kv_size(subscribed));

View File

@ -118,7 +118,7 @@ void msgpack_rpc_error(char *msg, msgpack_packer *res)
/// Serializes a msgpack-rpc request or notification(id == 0) /// Serializes a msgpack-rpc request or notification(id == 0)
WBuffer *serialize_request(uint64_t request_id, WBuffer *serialize_request(uint64_t request_id,
String method, String method,
Object arg, Array args,
msgpack_sbuffer *sbuffer, msgpack_sbuffer *sbuffer,
size_t refcount) size_t refcount)
FUNC_ATTR_NONNULL_ARG(4) FUNC_ATTR_NONNULL_ARG(4)
@ -134,12 +134,12 @@ WBuffer *serialize_request(uint64_t request_id,
msgpack_pack_raw(&pac, method.size); msgpack_pack_raw(&pac, method.size);
msgpack_pack_raw_body(&pac, method.data, method.size); msgpack_pack_raw_body(&pac, method.data, method.size);
msgpack_rpc_from_object(arg, &pac); msgpack_rpc_from_array(args, &pac);
WBuffer *rv = wstream_new_buffer(xmemdup(sbuffer->data, sbuffer->size), WBuffer *rv = wstream_new_buffer(xmemdup(sbuffer->data, sbuffer->size),
sbuffer->size, sbuffer->size,
refcount, refcount,
free); free);
msgpack_rpc_free_object(arg); msgpack_rpc_free_array(args);
msgpack_sbuffer_clear(sbuffer); msgpack_sbuffer_clear(sbuffer);
return rv; return rv;
} }

View File

@ -98,7 +98,7 @@ bool provider_register(char *method, uint64_t channel_id)
return true; return true;
} }
Object provider_call(char *method, Object arg) Object provider_call(char *method, Array args)
{ {
uint64_t channel_id = get_provider_for(method); uint64_t channel_id = get_provider_for(method);
@ -109,13 +109,13 @@ Object provider_call(char *method, Object arg)
"Provider for \"%s\" is not available", "Provider for \"%s\" is not available",
method); method);
report_error(buf); report_error(buf);
msgpack_rpc_free_object(arg); msgpack_rpc_free_array(args);
return NIL; return NIL;
} }
bool error = false; bool error = false;
Object result = NIL; Object result = NIL;
channel_send_call(channel_id, method, arg, &result, &error); channel_send_call(channel_id, method, args, &result, &error);
if (error) { if (error) {
report_error(result.data.string.data); report_error(result.data.string.data);