aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThiago de Arruda <tpadilha84@gmail.com>2014-08-29 22:27:54 -0300
committerThiago de Arruda <tpadilha84@gmail.com>2014-08-29 22:27:54 -0300
commitdf64c0f932c8c9d4cfbec8b54aefb6c5cc7c359e (patch)
tree330a542669f1adaf4ba0d8774975b4a04c5af128 /src
parent9d5e2c34c95739c8130f33aad8a18b19a281a1ad (diff)
parent887446a0382593ba5d3206eb4008df22457d57d7 (diff)
downloadrneovim-df64c0f932c8c9d4cfbec8b54aefb6c5cc7c359e.tar.gz
rneovim-df64c0f932c8c9d4cfbec8b54aefb6c5cc7c359e.tar.bz2
rneovim-df64c0f932c8c9d4cfbec8b54aefb6c5cc7c359e.zip
Merge PR #1121 'Full compliance with msgpack-RPC'
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c30
-rw-r--r--src/nvim/ex_cmds2.c20
-rw-r--r--src/nvim/ops.c10
-rw-r--r--src/nvim/os/channel.c44
-rw-r--r--src/nvim/os/msgpack_rpc.c18
-rw-r--r--src/nvim/os/msgpack_rpc.h7
-rw-r--r--src/nvim/os/provider.c6
-rw-r--r--src/nvim/os_unix.c2
8 files changed, 86 insertions, 51 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 1cef91785c..34af143446 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6493,8 +6493,8 @@ static struct fst {
{"searchpair", 3, 7, f_searchpair},
{"searchpairpos", 3, 7, f_searchpairpos},
{"searchpos", 1, 4, f_searchpos},
- {"send_call", 3, 3, f_send_call},
- {"send_event", 3, 3, f_send_event},
+ {"send_call", 2, 64, f_send_call},
+ {"send_event", 2, 64, f_send_event},
{"setbufvar", 3, 3, f_setbufvar},
{"setcmdpos", 1, 1, f_setcmdpos},
{"setline", 2, 2, f_setline},
@@ -12632,13 +12632,19 @@ static void f_send_call(typval_T *argvars, typval_T *rettv)
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;
Object result;
if (!channel_send_call((uint64_t)argvars[0].vval.v_number,
- (char *)argvars[1].vval.v_string,
- vim_to_object(&argvars[2]),
- &result,
- &errored)) {
+ (char *)argvars[1].vval.v_string,
+ args,
+ &result,
+ &errored)) {
EMSG2(_(e_invarg2), "Channel doesn't exist");
return;
}
@@ -12673,9 +12679,15 @@ static void f_send_event(typval_T *argvars, typval_T *rettv)
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,
(char *)argvars[1].vval.v_string,
- vim_to_object(&argvars[2]))) {
+ args)) {
EMSG2(_(e_invarg2), "Channel doesn't exist");
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)
{
- 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) {
return;
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index e0b0b55f41..3809858875 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -3251,8 +3251,9 @@ static void script_host_execute(char *method, exarg_T *eap)
char *script = (char *)script_get(eap, eap->arg);
if (!eap->skip) {
- String str = cstr_to_string(script ? script : (char *)eap->arg);
- Object result = provider_call(method, STRING_OBJ(str));
+ Array args = ARRAY_DICT_INIT;
+ 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
// returned something
msgpack_rpc_free_object(result);
@@ -3266,18 +3267,19 @@ static void script_host_execute_file(char *method, exarg_T *eap)
char buffer[MAXPATHL];
vim_FullName(eap->arg, (uint8_t *)buffer, sizeof(buffer), false);
- String file = cstr_to_string(buffer);
- Object result = provider_call(method, STRING_OBJ(file));
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, STRING_OBJ(cstr_to_string(buffer)));
+ Object result = provider_call(method, args);
msgpack_rpc_free_object(result);
}
static void script_host_do_range(char *method, exarg_T *eap)
{
- Array arg = {0, 0, 0};
- ADD(arg, INTEGER_OBJ(eap->line1));
- ADD(arg, INTEGER_OBJ(eap->line2));
- ADD(arg, STRING_OBJ(cstr_to_string((char *)eap->arg)));
- Object result = provider_call(method, ARRAY_OBJ(arg));
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(eap->line1));
+ ADD(args, INTEGER_OBJ(eap->line2));
+ ADD(args, STRING_OBJ(cstr_to_string((char *)eap->arg)));
+ Object result = provider_call(method, args);
msgpack_rpc_free_object(result);
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 0b0a913a95..f1cb34577b 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -5232,7 +5232,8 @@ static void get_clipboard(int name)
struct yankreg *reg = &y_regs[CLIP_REGISTER];
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) {
goto err;
@@ -5278,12 +5279,15 @@ static void set_clipboard(int name)
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++) {
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);
}
diff --git a/src/nvim/os/channel.c b/src/nvim/os/channel.c
index 2c1928f3b3..39455df862 100644
--- a/src/nvim/os/channel.c
+++ b/src/nvim/os/channel.c
@@ -143,40 +143,48 @@ bool channel_exists(uint64_t id)
&& 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
/// channels that have subscribed to the event type
/// @param name The event name, an arbitrary string
-/// @param arg The event arg
-/// @return True if the data was sent successfully, false otherwise.
-bool channel_send_event(uint64_t id, char *name, Object arg)
+/// @param args Array with event arguments
+/// @return True if the event was sent successfully, false otherwise.
+bool channel_send_event(uint64_t id, char *name, Array args)
{
Channel *channel = NULL;
if (id > 0) {
if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
return false;
}
- send_event(channel, name, arg);
+ send_event(channel, name, args);
} else {
- broadcast_event(name, arg);
+ broadcast_event(name, args);
}
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,
char *name,
- Object arg,
+ Array args,
Object *result,
bool *errored)
{
Channel *channel = NULL;
if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
return false;
}
@@ -190,13 +198,13 @@ bool channel_send_call(uint64_t id,
"while processing a RPC call",
channel->id);
*result = STRING_OBJ(cstr_to_string(buf));
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
return false;
}
uint64_t request_id = channel->next_request_id++;
// 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
? 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,
uint64_t id,
char *name,
- Object arg)
+ Array args)
{
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,
char *name,
- Object arg)
+ Array args)
{
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;
kv_init(subscribed);
@@ -442,14 +450,14 @@ static void broadcast_event(char *name, Object arg)
});
if (!kv_size(subscribed)) {
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
goto end;
}
String method = {.size = strlen(name), .data = name};
WBuffer *buffer = serialize_request(0,
method,
- arg,
+ args,
&out_buffer,
kv_size(subscribed));
diff --git a/src/nvim/os/msgpack_rpc.c b/src/nvim/os/msgpack_rpc.c
index c03d8dccca..c6e2af2f1c 100644
--- a/src/nvim/os/msgpack_rpc.c
+++ b/src/nvim/os/msgpack_rpc.c
@@ -39,15 +39,14 @@ WBuffer *msgpack_rpc_call(uint64_t channel_id,
return serialize_response(response_id, err, NIL, sbuffer);
}
- uint64_t method_id = req->via.array.ptr[2].via.u64;
-
- if (method_id == 0) {
+ if (req->via.array.ptr[2].type == MSGPACK_OBJECT_POSITIVE_INTEGER
+ && req->via.array.ptr[2].via.u64 == 0) {
return serialize_metadata(response_id, channel_id, sbuffer);
}
// dispatch the call
Error error = { .set = false };
- Object rv = msgpack_rpc_dispatch(channel_id, method_id, req, &error);
+ Object rv = msgpack_rpc_dispatch(channel_id, req, &error);
// send the response
msgpack_packer response;
msgpack_packer_init(&response, sbuffer, msgpack_sbuffer_write);
@@ -119,7 +118,7 @@ void msgpack_rpc_error(char *msg, msgpack_packer *res)
/// Serializes a msgpack-rpc request or notification(id == 0)
WBuffer *serialize_request(uint64_t request_id,
String method,
- Object arg,
+ Array args,
msgpack_sbuffer *sbuffer,
size_t refcount)
FUNC_ATTR_NONNULL_ARG(4)
@@ -135,12 +134,12 @@ WBuffer *serialize_request(uint64_t request_id,
msgpack_pack_raw(&pac, 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),
sbuffer->size,
refcount,
free);
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
msgpack_sbuffer_clear(sbuffer);
return rv;
}
@@ -235,8 +234,9 @@ static char *msgpack_rpc_validate(uint64_t *response_id, msgpack_object *req)
return "Message type must be 0";
}
- if (req->via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER) {
- return "Method id must be a positive integer";
+ if (req->via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER
+ && req->via.array.ptr[2].type != MSGPACK_OBJECT_RAW) {
+ return "Method must be a positive integer or a string";
}
if (req->via.array.ptr[3].type != MSGPACK_OBJECT_ARRAY) {
diff --git a/src/nvim/os/msgpack_rpc.h b/src/nvim/os/msgpack_rpc.h
index 5aca900d2e..35f175d2a0 100644
--- a/src/nvim/os/msgpack_rpc.h
+++ b/src/nvim/os/msgpack_rpc.h
@@ -21,6 +21,11 @@ typedef Object (*rpc_method_handler_fn)(uint64_t channel_id,
msgpack_object *req,
Error *error);
+
+/// Initializes the msgpack-rpc method table
+void msgpack_rpc_init(void);
+
+
/// Dispatches to the actual API function after basic payload validation by
/// `msgpack_rpc_call`. It is responsible for validating/converting arguments
/// to C types, and converting the return value back to msgpack types.
@@ -33,11 +38,11 @@ typedef Object (*rpc_method_handler_fn)(uint64_t channel_id,
/// @param error Pointer to error structure
/// @return Some object
Object msgpack_rpc_dispatch(uint64_t channel_id,
- uint64_t method_id,
msgpack_object *req,
Error *error)
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3);
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/msgpack_rpc.h.generated.h"
#endif
diff --git a/src/nvim/os/provider.c b/src/nvim/os/provider.c
index d94203f683..07e757fe0e 100644
--- a/src/nvim/os/provider.c
+++ b/src/nvim/os/provider.c
@@ -98,7 +98,7 @@ bool provider_register(char *method, uint64_t channel_id)
return true;
}
-Object provider_call(char *method, Object arg)
+Object provider_call(char *method, Array args)
{
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",
method);
report_error(buf);
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
return NIL;
}
bool error = false;
Object result = NIL;
- channel_send_call(channel_id, method, arg, &result, &error);
+ channel_send_call(channel_id, method, args, &result, &error);
if (error) {
report_error(result.data.string.data);
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index 1b092c8261..33b08d7df6 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -54,6 +54,7 @@
#include "nvim/os/shell.h"
#include "nvim/os/signal.h"
#include "nvim/os/job.h"
+#include "nvim/os/msgpack_rpc.h"
#if defined(HAVE_SYS_IOCTL_H)
# include <sys/ioctl.h>
@@ -164,6 +165,7 @@ void mch_init(void)
mac_conv_init();
#endif
+ msgpack_rpc_init();
event_init();
}