diff options
Diffstat (limited to 'src/nvim/msgpack_rpc')
| -rw-r--r-- | src/nvim/msgpack_rpc/channel.c | 79 | ||||
| -rw-r--r-- | src/nvim/msgpack_rpc/helpers.c | 458 | ||||
| -rw-r--r-- | src/nvim/msgpack_rpc/server.c | 3 |
3 files changed, 367 insertions, 173 deletions
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 3a6d7c1434..5b249ee1c7 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -16,6 +16,7 @@ #include "nvim/event/socket.h" #include "nvim/msgpack_rpc/helpers.h" #include "nvim/vim.h" +#include "nvim/main.h" #include "nvim/ascii.h" #include "nvim/memory.h" #include "nvim/os_unix.h" @@ -119,7 +120,7 @@ void channel_teardown(void) uint64_t channel_from_process(char **argv) { Channel *channel = register_channel(kChannelTypeProc); - channel->data.process.uvproc = libuv_process_init(&loop, channel); + channel->data.process.uvproc = libuv_process_init(&main_loop, channel); Process *proc = &channel->data.process.uvproc.process; proc->argv = argv; proc->in = &channel->data.process.in; @@ -127,7 +128,7 @@ uint64_t channel_from_process(char **argv) proc->err = &channel->data.process.err; proc->cb = process_exit; if (!process_spawn(proc)) { - loop_poll_events(&loop, 0); + loop_poll_events(&main_loop, 0); decref(channel); return 0; } @@ -179,7 +180,7 @@ bool channel_send_event(uint64_t id, char *name, Array args) // Pending request, queue the notification for later sending. String method = cstr_as_string(name); WBuffer *buffer = serialize_request(id, 0, method, args, &out_buffer, 1); - kv_push(WBuffer *, channel->delayed_notifications, buffer); + kv_push(channel->delayed_notifications, buffer); } else { send_event(channel, name, args); } @@ -217,10 +218,10 @@ Object channel_send_call(uint64_t id, send_request(channel, request_id, method_name, args); // Push the frame - ChannelCallFrame frame = {request_id, false, false, NIL}; - kv_push(ChannelCallFrame *, channel->call_stack, &frame); + ChannelCallFrame frame = { request_id, false, false, NIL }; + kv_push(channel->call_stack, &frame); channel->pending_requests++; - LOOP_PROCESS_EVENTS_UNTIL(&loop, channel->events, -1, frame.returned); + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned); (void)kv_pop(channel->call_stack); channel->pending_requests--; @@ -316,11 +317,11 @@ void channel_from_stdio(void) Channel *channel = register_channel(kChannelTypeStdio); incref(channel); // stdio channels are only closed on exit // read stream - rstream_init_fd(&loop, &channel->data.std.in, 0, CHANNEL_BUFFER_SIZE, - channel); + rstream_init_fd(&main_loop, &channel->data.std.in, 0, CHANNEL_BUFFER_SIZE, + channel); rstream_start(&channel->data.std.in, parse_msgpack); // write stream - wstream_init_fd(&loop, &channel->data.std.out, 1, 0, NULL); + wstream_init_fd(&main_loop, &channel->data.std.out, 1, 0, NULL); } static void forward_stderr(Stream *stream, RBuffer *rbuf, size_t count, @@ -574,13 +575,12 @@ static void send_event(Channel *channel, static void broadcast_event(char *name, Array args) { - kvec_t(Channel *) subscribed; - kv_init(subscribed); + kvec_t(Channel *) subscribed = KV_INITIAL_VALUE; Channel *channel; map_foreach_value(channels, channel, { if (pmap_has(cstr_t)(channel->subscribed_events, name)) { - kv_push(Channel *, subscribed, channel); + kv_push(subscribed, channel); } }); @@ -600,7 +600,7 @@ static void broadcast_event(char *name, Array args) for (size_t i = 0; i < kv_size(subscribed); i++) { Channel *channel = kv_A(subscribed, i); if (channel->pending_requests) { - kv_push(WBuffer *, channel->delayed_notifications, buffer); + kv_push(channel->delayed_notifications, buffer); } else { channel_write(channel, buffer); } @@ -647,7 +647,7 @@ static void close_channel(Channel *channel) case kChannelTypeStdio: stream_close(&channel->data.std.in, NULL); stream_close(&channel->data.std.out, NULL); - queue_put(loop.fast_events, exit_event, 1, channel); + queue_put(main_loop.fast_events, exit_event, 1, channel); return; default: abort(); @@ -692,7 +692,7 @@ static void close_cb(Stream *stream, void *data) static Channel *register_channel(ChannelType type) { Channel *rv = xmalloc(sizeof(Channel)); - rv->events = queue_new_child(loop.events); + rv->events = queue_new_child(main_loop.events); rv->type = type; rv->refcount = 1; rv->closed = false; @@ -816,20 +816,55 @@ static void decref(Channel *channel) #define REQ "[request] " #define RES "[response] " #define NOT "[notification] " +#define ERR "[error] " + +// Cannot define array with negative offsets, so this one is needed to be added +// to MSGPACK_UNPACK_\* values. +#define MUR_OFF 2 + +static const char *const msgpack_error_messages[] = { + [MSGPACK_UNPACK_EXTRA_BYTES + MUR_OFF] = "extra bytes found", + [MSGPACK_UNPACK_CONTINUE + MUR_OFF] = "incomplete string", + [MSGPACK_UNPACK_PARSE_ERROR + MUR_OFF] = "parse error", + [MSGPACK_UNPACK_NOMEM_ERROR + MUR_OFF] = "not enough memory", +}; static void log_server_msg(uint64_t channel_id, msgpack_sbuffer *packed) { msgpack_unpacked unpacked; msgpack_unpacked_init(&unpacked); - msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL); - uint64_t type = unpacked.data.via.array.ptr[0].via.u64; DLOGN("[msgpack-rpc] nvim -> client(%" PRIu64 ") ", channel_id); - log_lock(); - FILE *f = open_log_file(); - fprintf(f, type ? (type == 1 ? RES : NOT) : REQ); - log_msg_close(f, unpacked.data); - msgpack_unpacked_destroy(&unpacked); + const msgpack_unpack_return result = + msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL); + switch (result) { + case MSGPACK_UNPACK_SUCCESS: { + uint64_t type = unpacked.data.via.array.ptr[0].via.u64; + log_lock(); + FILE *f = open_log_file(); + fprintf(f, type ? (type == 1 ? RES : NOT) : REQ); + log_msg_close(f, unpacked.data); + msgpack_unpacked_destroy(&unpacked); + break; + } + case MSGPACK_UNPACK_EXTRA_BYTES: + case MSGPACK_UNPACK_CONTINUE: + case MSGPACK_UNPACK_PARSE_ERROR: + case MSGPACK_UNPACK_NOMEM_ERROR: { + log_lock(); + FILE *f = open_log_file(); + fprintf(f, ERR); + log_msg_close(f, (msgpack_object) { + .type = MSGPACK_OBJECT_STR, + .via.str = { + .ptr = (char *)msgpack_error_messages[result + MUR_OFF], + .size = (uint32_t)strlen( + msgpack_error_messages[result + MUR_OFF]), + }, + }); + break; + } + } } static void log_client_msg(uint64_t channel_id, diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 0049ae6b95..9195b10614 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -7,9 +7,11 @@ #include "nvim/api/private/helpers.h" #include "nvim/msgpack_rpc/helpers.h" #include "nvim/msgpack_rpc/defs.h" +#include "nvim/lib/kvec.h" #include "nvim/vim.h" #include "nvim/log.h" #include "nvim/memory.h" +#include "nvim/assert.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/helpers.c.generated.h" @@ -18,39 +20,39 @@ static msgpack_zone zone; static msgpack_sbuffer sbuffer; -#define HANDLE_TYPE_CONVERSION_IMPL(t, lt) \ - bool msgpack_rpc_to_##lt(msgpack_object *obj, t *arg) \ - FUNC_ATTR_NONNULL_ALL \ - { \ - if (obj->type != MSGPACK_OBJECT_EXT \ - || obj->via.ext.type != kObjectType##t) { \ - return false; \ - } \ - \ - msgpack_object data; \ - msgpack_unpack_return ret = msgpack_unpack(obj->via.ext.ptr, \ - obj->via.ext.size, \ - NULL, \ - &zone, \ - &data); \ - \ - if (ret != MSGPACK_UNPACK_SUCCESS) { \ - return false; \ - } \ - \ - *arg = data.via.u64; \ - return true; \ - } \ - \ - void msgpack_rpc_from_##lt(t o, msgpack_packer *res) \ - FUNC_ATTR_NONNULL_ARG(2) \ - { \ - msgpack_packer pac; \ - msgpack_packer_init(&pac, &sbuffer, msgpack_sbuffer_write); \ - msgpack_pack_uint64(&pac, o); \ - msgpack_pack_ext(res, sbuffer.size, kObjectType##t); \ - msgpack_pack_ext_body(res, sbuffer.data, sbuffer.size); \ - msgpack_sbuffer_clear(&sbuffer); \ +#define HANDLE_TYPE_CONVERSION_IMPL(t, lt) \ + bool msgpack_rpc_to_##lt(const msgpack_object *const obj, t *const arg) \ + FUNC_ATTR_NONNULL_ALL \ + { \ + if (obj->type != MSGPACK_OBJECT_EXT \ + || obj->via.ext.type != kObjectType##t) { \ + return false; \ + } \ + \ + msgpack_object data; \ + msgpack_unpack_return ret = msgpack_unpack(obj->via.ext.ptr, \ + obj->via.ext.size, \ + NULL, \ + &zone, \ + &data); \ + \ + if (ret != MSGPACK_UNPACK_SUCCESS) { \ + return false; \ + } \ + \ + *arg = data.via.u64; \ + return true; \ + } \ + \ + void msgpack_rpc_from_##lt(t o, msgpack_packer *res) \ + FUNC_ATTR_NONNULL_ARG(2) \ + { \ + msgpack_packer pac; \ + msgpack_packer_init(&pac, &sbuffer, msgpack_sbuffer_write); \ + msgpack_pack_uint64(&pac, o); \ + msgpack_pack_ext(res, sbuffer.size, kObjectType##t); \ + msgpack_pack_ext_body(res, sbuffer.data, sbuffer.size); \ + msgpack_sbuffer_clear(&sbuffer); \ } void msgpack_rpc_helpers_init(void) @@ -63,34 +65,182 @@ HANDLE_TYPE_CONVERSION_IMPL(Buffer, buffer) HANDLE_TYPE_CONVERSION_IMPL(Window, window) HANDLE_TYPE_CONVERSION_IMPL(Tabpage, tabpage) -bool msgpack_rpc_to_boolean(msgpack_object *obj, Boolean *arg) +typedef struct { + const msgpack_object *mobj; + Object *aobj; + bool container; + size_t idx; +} MPToAPIObjectStackItem; + +/// Convert type used by msgpack parser to Neovim own API type +/// +/// @param[in] obj Msgpack value to convert. +/// @param[out] arg Location where result of conversion will be saved. +/// +/// @return true in case of success, false otherwise. +bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) FUNC_ATTR_NONNULL_ALL { - *arg = obj->via.boolean; - return obj->type == MSGPACK_OBJECT_BOOLEAN; -} - -bool msgpack_rpc_to_integer(msgpack_object *obj, Integer *arg) - FUNC_ATTR_NONNULL_ALL -{ - if (obj->type == MSGPACK_OBJECT_POSITIVE_INTEGER - && obj->via.u64 <= INT64_MAX) { - *arg = (int64_t)obj->via.u64; - return true; + bool ret = true; + kvec_t(MPToAPIObjectStackItem) stack = KV_INITIAL_VALUE; + kv_push(stack, ((MPToAPIObjectStackItem) { obj, arg, false, 0 })); + while (ret && kv_size(stack)) { + MPToAPIObjectStackItem cur = kv_last(stack); + if (!cur.container) { + *cur.aobj = NIL; + } + switch (cur.mobj->type) { + case MSGPACK_OBJECT_NIL: { + break; + } + case MSGPACK_OBJECT_BOOLEAN: { + *cur.aobj = BOOLEAN_OBJ(cur.mobj->via.boolean); + break; + } + case MSGPACK_OBJECT_NEGATIVE_INTEGER: { + STATIC_ASSERT(sizeof(Integer) == sizeof(cur.mobj->via.i64), + "Msgpack integer size does not match API integer"); + *cur.aobj = INTEGER_OBJ(cur.mobj->via.i64); + break; + } + case MSGPACK_OBJECT_POSITIVE_INTEGER: { + STATIC_ASSERT(sizeof(Integer) == sizeof(cur.mobj->via.u64), + "Msgpack integer size does not match API integer"); + if (cur.mobj->via.u64 > API_INTEGER_MAX) { + ret = false; + } else { + *cur.aobj = INTEGER_OBJ((Integer)cur.mobj->via.u64); + } + break; + } + case MSGPACK_OBJECT_FLOAT: { + STATIC_ASSERT(sizeof(Float) == sizeof(cur.mobj->via.f64), + "Msgpack floating-point size does not match API integer"); + *cur.aobj = FLOATING_OBJ(cur.mobj->via.f64); + break; + } +#define STR_CASE(type, attr, obj, dest, conv) \ + case type: { \ + dest = conv(((String) { \ + .size = obj->via.attr.size, \ + .data = (obj->via.attr.ptr == NULL || obj->via.attr.size == 0 \ + ? NULL \ + : xmemdupz(obj->via.attr.ptr, obj->via.attr.size)), \ + })); \ + break; \ + } + STR_CASE(MSGPACK_OBJECT_STR, str, cur.mobj, *cur.aobj, STRING_OBJ) + STR_CASE(MSGPACK_OBJECT_BIN, bin, cur.mobj, *cur.aobj, STRING_OBJ) + case MSGPACK_OBJECT_ARRAY: { + const size_t size = cur.mobj->via.array.size; + if (cur.container) { + if (cur.idx >= size) { + (void)kv_pop(stack); + } else { + const size_t idx = cur.idx; + cur.idx++; + kv_last(stack) = cur; + kv_push(stack, ((MPToAPIObjectStackItem) { + .mobj = &cur.mobj->via.array.ptr[idx], + .aobj = &cur.aobj->data.array.items[idx], + .container = false, + })); + } + } else { + *cur.aobj = ARRAY_OBJ(((Array) { + .size = size, + .capacity = size, + .items = (size > 0 + ? xcalloc(size, sizeof(*cur.aobj->data.array.items)) + : NULL), + })); + cur.container = true; + kv_last(stack) = cur; + } + break; + } + case MSGPACK_OBJECT_MAP: { + const size_t size = cur.mobj->via.map.size; + if (cur.container) { + if (cur.idx >= size) { + (void)kv_pop(stack); + } else { + const size_t idx = cur.idx; + cur.idx++; + kv_last(stack) = cur; + const msgpack_object *const key = &cur.mobj->via.map.ptr[idx].key; + switch (key->type) { +#define ID(x) x + STR_CASE(MSGPACK_OBJECT_STR, str, key, + cur.aobj->data.dictionary.items[idx].key, ID) + STR_CASE(MSGPACK_OBJECT_BIN, bin, key, + cur.aobj->data.dictionary.items[idx].key, ID) +#undef ID + case MSGPACK_OBJECT_NIL: + case MSGPACK_OBJECT_BOOLEAN: + case MSGPACK_OBJECT_POSITIVE_INTEGER: + case MSGPACK_OBJECT_NEGATIVE_INTEGER: + case MSGPACK_OBJECT_FLOAT: + case MSGPACK_OBJECT_EXT: + case MSGPACK_OBJECT_MAP: + case MSGPACK_OBJECT_ARRAY: { + ret = false; + break; + } + } + if (ret) { + kv_push(stack, ((MPToAPIObjectStackItem) { + .mobj = &cur.mobj->via.map.ptr[idx].val, + .aobj = &cur.aobj->data.dictionary.items[idx].value, + .container = false, + })); + } + } + } else { + *cur.aobj = DICTIONARY_OBJ(((Dictionary) { + .size = size, + .capacity = size, + .items = (size > 0 + ? xcalloc(size, sizeof(*cur.aobj->data.dictionary.items)) + : NULL), + })); + cur.container = true; + kv_last(stack) = cur; + } + break; + } + case MSGPACK_OBJECT_EXT: { + switch (cur.mobj->via.ext.type) { + case kObjectTypeBuffer: { + cur.aobj->type = kObjectTypeBuffer; + ret = msgpack_rpc_to_buffer(cur.mobj, &cur.aobj->data.buffer); + break; + } + case kObjectTypeWindow: { + cur.aobj->type = kObjectTypeWindow; + ret = msgpack_rpc_to_window(cur.mobj, &cur.aobj->data.window); + break; + } + case kObjectTypeTabpage: { + cur.aobj->type = kObjectTypeTabpage; + ret = msgpack_rpc_to_tabpage(cur.mobj, &cur.aobj->data.tabpage); + break; + } + } + break; + } +#undef STR_CASE + } + if (!cur.container) { + (void)kv_pop(stack); + } } - - *arg = obj->via.i64; - return obj->type == MSGPACK_OBJECT_NEGATIVE_INTEGER; + kv_destroy(stack); + return ret; } -bool msgpack_rpc_to_float(msgpack_object *obj, Float *arg) - FUNC_ATTR_NONNULL_ALL -{ - *arg = obj->via.f64; - return obj->type == MSGPACK_OBJECT_FLOAT; -} - -bool msgpack_rpc_to_string(msgpack_object *obj, String *arg) +static bool msgpack_rpc_to_string(const msgpack_object *const obj, + String *const arg) FUNC_ATTR_NONNULL_ALL { if (obj->type == MSGPACK_OBJECT_BIN || obj->type == MSGPACK_OBJECT_STR) { @@ -103,58 +253,7 @@ bool msgpack_rpc_to_string(msgpack_object *obj, String *arg) return false; } -bool msgpack_rpc_to_object(msgpack_object *obj, Object *arg) - FUNC_ATTR_NONNULL_ALL -{ - switch (obj->type) { - case MSGPACK_OBJECT_NIL: - arg->type = kObjectTypeNil; - return true; - - case MSGPACK_OBJECT_BOOLEAN: - arg->type = kObjectTypeBoolean; - return msgpack_rpc_to_boolean(obj, &arg->data.boolean); - - case MSGPACK_OBJECT_POSITIVE_INTEGER: - case MSGPACK_OBJECT_NEGATIVE_INTEGER: - arg->type = kObjectTypeInteger; - return msgpack_rpc_to_integer(obj, &arg->data.integer); - - case MSGPACK_OBJECT_FLOAT: - arg->type = kObjectTypeFloat; - return msgpack_rpc_to_float(obj, &arg->data.floating); - - case MSGPACK_OBJECT_BIN: - case MSGPACK_OBJECT_STR: - arg->type = kObjectTypeString; - return msgpack_rpc_to_string(obj, &arg->data.string); - - case MSGPACK_OBJECT_ARRAY: - arg->type = kObjectTypeArray; - return msgpack_rpc_to_array(obj, &arg->data.array); - - case MSGPACK_OBJECT_MAP: - arg->type = kObjectTypeDictionary; - return msgpack_rpc_to_dictionary(obj, &arg->data.dictionary); - - case MSGPACK_OBJECT_EXT: - switch (obj->via.ext.type) { - case kObjectTypeBuffer: - arg->type = kObjectTypeBuffer; - return msgpack_rpc_to_buffer(obj, &arg->data.buffer); - case kObjectTypeWindow: - arg->type = kObjectTypeWindow; - return msgpack_rpc_to_window(obj, &arg->data.window); - case kObjectTypeTabpage: - arg->type = kObjectTypeTabpage; - return msgpack_rpc_to_tabpage(obj, &arg->data.tabpage); - } - default: - return false; - } -} - -bool msgpack_rpc_to_array(msgpack_object *obj, Array *arg) +bool msgpack_rpc_to_array(const msgpack_object *const obj, Array *const arg) FUNC_ATTR_NONNULL_ALL { if (obj->type != MSGPACK_OBJECT_ARRAY) { @@ -173,7 +272,8 @@ bool msgpack_rpc_to_array(msgpack_object *obj, Array *arg) return true; } -bool msgpack_rpc_to_dictionary(msgpack_object *obj, Dictionary *arg) +bool msgpack_rpc_to_dictionary(const msgpack_object *const obj, + Dictionary *const arg) FUNC_ATTR_NONNULL_ALL { if (obj->type != MSGPACK_OBJECT_MAP) { @@ -228,50 +328,108 @@ void msgpack_rpc_from_string(String result, msgpack_packer *res) msgpack_pack_str_body(res, result.data, result.size); } -void msgpack_rpc_from_object(Object result, msgpack_packer *res) +typedef struct { + const Object *aobj; + bool container; + size_t idx; +} APIToMPObjectStackItem; + +/// Convert type used by Neovim API to msgpack +/// +/// @param[in] result Object to convert. +/// @param[out] res Structure that defines where conversion results are saved. +/// +/// @return true in case of success, false otherwise. +void msgpack_rpc_from_object(const Object result, msgpack_packer *const res) FUNC_ATTR_NONNULL_ARG(2) { - switch (result.type) { - case kObjectTypeNil: - msgpack_pack_nil(res); - break; - - case kObjectTypeBoolean: - msgpack_rpc_from_boolean(result.data.boolean, res); - break; - - case kObjectTypeInteger: - msgpack_rpc_from_integer(result.data.integer, res); - break; - - case kObjectTypeFloat: - msgpack_rpc_from_float(result.data.floating, res); - break; - - case kObjectTypeString: - msgpack_rpc_from_string(result.data.string, res); - break; - - case kObjectTypeArray: - msgpack_rpc_from_array(result.data.array, res); - break; - - case kObjectTypeBuffer: - msgpack_rpc_from_buffer(result.data.buffer, res); - break; - - case kObjectTypeWindow: - msgpack_rpc_from_window(result.data.window, res); - break; - - case kObjectTypeTabpage: - msgpack_rpc_from_tabpage(result.data.tabpage, res); - break; - - case kObjectTypeDictionary: - msgpack_rpc_from_dictionary(result.data.dictionary, res); - break; + kvec_t(APIToMPObjectStackItem) stack = KV_INITIAL_VALUE; + kv_push(stack, ((APIToMPObjectStackItem) { &result, false, 0 })); + while (kv_size(stack)) { + APIToMPObjectStackItem cur = kv_last(stack); + switch (cur.aobj->type) { + case kObjectTypeNil: { + msgpack_pack_nil(res); + break; + } + case kObjectTypeBoolean: { + msgpack_rpc_from_boolean(cur.aobj->data.boolean, res); + break; + } + case kObjectTypeInteger: { + msgpack_rpc_from_integer(cur.aobj->data.integer, res); + break; + } + case kObjectTypeFloat: { + msgpack_rpc_from_float(cur.aobj->data.floating, res); + break; + } + case kObjectTypeString: { + msgpack_rpc_from_string(cur.aobj->data.string, res); + break; + } + case kObjectTypeBuffer: { + msgpack_rpc_from_buffer(cur.aobj->data.buffer, res); + break; + } + case kObjectTypeWindow: { + msgpack_rpc_from_window(cur.aobj->data.window, res); + break; + } + case kObjectTypeTabpage: { + msgpack_rpc_from_tabpage(cur.aobj->data.tabpage, res); + break; + } + case kObjectTypeArray: { + const size_t size = cur.aobj->data.array.size; + if (cur.container) { + if (cur.idx >= size) { + (void)kv_pop(stack); + } else { + const size_t idx = cur.idx; + cur.idx++; + kv_last(stack) = cur; + kv_push(stack, ((APIToMPObjectStackItem) { + .aobj = &cur.aobj->data.array.items[idx], + .container = false, + })); + } + } else { + msgpack_pack_array(res, size); + cur.container = true; + kv_last(stack) = cur; + } + break; + } + case kObjectTypeDictionary: { + const size_t size = cur.aobj->data.dictionary.size; + if (cur.container) { + if (cur.idx >= size) { + (void)kv_pop(stack); + } else { + const size_t idx = cur.idx; + cur.idx++; + kv_last(stack) = cur; + msgpack_rpc_from_string(cur.aobj->data.dictionary.items[idx].key, + res); + kv_push(stack, ((APIToMPObjectStackItem) { + .aobj = &cur.aobj->data.dictionary.items[idx].value, + .container = false, + })); + } + } else { + msgpack_pack_map(res, size); + cur.container = true; + kv_last(stack) = cur; + } + break; + } + } + if (!cur.container) { + (void)kv_pop(stack); + } } + kv_destroy(stack); } void msgpack_rpc_from_array(Array result, msgpack_packer *res) diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 6cc56ba3dd..abbd3e8aff 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -12,6 +12,7 @@ #include "nvim/eval.h" #include "nvim/garray.h" #include "nvim/vim.h" +#include "nvim/main.h" #include "nvim/memory.h" #include "nvim/log.h" #include "nvim/fileio.h" @@ -108,7 +109,7 @@ int server_start(const char *endpoint) } SocketWatcher *watcher = xmalloc(sizeof(SocketWatcher)); - socket_watcher_init(&loop, watcher, endpoint, NULL); + socket_watcher_init(&main_loop, watcher, endpoint, NULL); // Check if a watcher for the endpoint already exists for (int i = 0; i < watchers.ga_len; i++) { |