From 064483a2b4a3056baf8eee4424bb81127e531991 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 28 May 2024 12:52:24 +0200 Subject: refactor(fileio): use a linear buffer for FileDescriptor Using a ring buffer for buffered synchronous fileio is just unnecessary complexity. - when reading, we always consume the _entire_ buffer before getting into syscalls. Thus we reset the buffer to its initial position before when we actually read. - when writing and buffer is full, we always flush the entire buffer before starting to buffer again. So we can reset the buffer to its initial state. Also no static buffers are needed for writing and skipping. Needing an extra copy for each write completely defeated the purpose of a ring buffer (if there had been one) --- src/nvim/msgpack_rpc/packer.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/packer.c b/src/nvim/msgpack_rpc/packer.c index cac68f76f0..9c0d2910fa 100644 --- a/src/nvim/msgpack_rpc/packer.c +++ b/src/nvim/msgpack_rpc/packer.c @@ -113,7 +113,6 @@ void mpack_handle(ObjectType type, handle_T handle, PackerBuffer *packer) mpack_w(&packer->ptr, 0xc7); mpack_w(&packer->ptr, packsize); mpack_w(&packer->ptr, exttype); - // check_buffer(packer); memcpy(packer->ptr, buf, (size_t)packsize); packer->ptr += packsize; } -- cgit From c13c50b752dca322a5ec77dea6188c9e3694549b Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 30 May 2024 12:59:02 +0200 Subject: refactor(io): separate types for read and write streams This is a structural refactor with no logical changes, yet. Done in preparation for simplifying rstream/rbuffer which will require more state inline in RStream. The initial idea was to have RStream and WStream as sub-types symetrically but that doesn't work, as sockets are both reading and writing. Also there is very little write-specific state to start with, so the benefit of a separate WStream struct is a lot smaller. Just document what fields in `Stream` are write specific. --- src/nvim/msgpack_rpc/channel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 5737a0440f..98d5d8c6cb 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -89,7 +89,7 @@ void rpc_start(Channel *channel) kv_init(rpc->call_stack); if (channel->streamtype != kChannelStreamInternal) { - Stream *out = channel_outstream(channel); + RStream *out = channel_outstream(channel); #ifdef NVIM_LOG_DEBUG Stream *in = channel_instream(channel); DLOG("rpc ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id, @@ -202,7 +202,7 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem return frame.errored ? NIL : frame.result; } -static void receive_msgpack(Stream *stream, RBuffer *rbuf, size_t c, void *data, bool eof) +static void receive_msgpack(RStream *stream, RBuffer *rbuf, size_t c, void *data, bool eof) { Channel *channel = data; channel_incref(channel); -- cgit From 200e7ad1578619e78c664bd0c6be024168433412 Mon Sep 17 00:00:00 2001 From: James Tirta Halim Date: Mon, 3 Jun 2024 11:10:30 +0700 Subject: fixup: apply the change on more files --- src/nvim/msgpack_rpc/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 56b03d67d0..341f638a55 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -131,7 +131,7 @@ bool server_owns_pipe_address(const char *path) /// @returns 0: success, 1: validation error, 2: already listening, -errno: failed to bind/listen. int server_start(const char *addr) { - if (addr == NULL || addr[0] == '\0') { + if (addr == NULL || addr[0] == NUL) { WLOG("Empty or NULL address"); return 1; } -- cgit From 46b69aaf14a7da2c2ce800aa0eaec5eb019991b4 Mon Sep 17 00:00:00 2001 From: James Tirta Halim Date: Mon, 3 Jun 2024 11:13:55 +0700 Subject: fixup: include nvim/ascii_defs.h --- src/nvim/msgpack_rpc/server.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 341f638a55..24bd343a34 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -4,6 +4,7 @@ #include #include +#include "nvim/ascii_defs.h" #include "nvim/channel.h" #include "nvim/eval.h" #include "nvim/event/defs.h" -- cgit From 78d21593a35cf89692224f1000a04d3c9fff8add Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 31 May 2024 14:40:53 +0200 Subject: refactor(io): make rstream use a linear buffer If you like it you shouldn't put a ring on it. This is what _every_ consumer of RStream used anyway, either by calling rbuffer_reset, or rbuffer_consumed_compact (same as rbuffer_reset without needing a scratch buffer), or by consuming everything in each stream_read_cb call directly. --- src/nvim/msgpack_rpc/channel.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 98d5d8c6cb..6a0dc10214 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -31,8 +31,6 @@ #include "nvim/msgpack_rpc/packer.h" #include "nvim/msgpack_rpc/unpacker.h" #include "nvim/os/input.h" -#include "nvim/rbuffer.h" -#include "nvim/rbuffer_defs.h" #include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/ui_client.h" @@ -202,10 +200,25 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem return frame.errored ? NIL : frame.result; } -static void receive_msgpack(RStream *stream, RBuffer *rbuf, size_t c, void *data, bool eof) +static size_t receive_msgpack(RStream *stream, const char *rbuf, size_t c, void *data, bool eof) { Channel *channel = data; channel_incref(channel); + size_t consumed = 0; + + DLOG("ch %" PRIu64 ": parsing %zu bytes from msgpack Stream: %p", + channel->id, c, (void *)stream); + + if (c > 0) { + Unpacker *p = channel->rpc.unpacker; + p->read_ptr = rbuf; + p->read_size = c; + parse_msgpack(channel); + + if (!unpacker_closed(p)) { + consumed = c - p->read_size; + } + } if (eof) { channel_close(channel->id, kChannelPartRpc, NULL); @@ -213,25 +226,10 @@ static void receive_msgpack(RStream *stream, RBuffer *rbuf, size_t c, void *data snprintf(buf, sizeof(buf), "ch %" PRIu64 " was closed by the client", channel->id); chan_close_with_error(channel, buf, LOGLVL_INF); - goto end; - } - - DLOG("ch %" PRIu64 ": parsing %zu bytes from msgpack Stream: %p", - channel->id, rbuffer_size(rbuf), (void *)stream); - - Unpacker *p = channel->rpc.unpacker; - size_t size = 0; - p->read_ptr = rbuffer_read_ptr(rbuf, &size); - p->read_size = size; - parse_msgpack(channel); - - if (!unpacker_closed(p)) { - size_t consumed = size - p->read_size; - rbuffer_consumed_compact(rbuf, consumed); } -end: channel_decref(channel); + return consumed; } static ChannelCallFrame *find_call_frame(RpcState *rpc, uint32_t request_id) -- cgit From 19052e0a06240be018a234d87f51113eca6d17fa Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 8 Jun 2024 14:19:30 +0200 Subject: refactor(shada): use msgpack_sbuffer less Work towards getting rid of libmsgpack depedency eventually. msgpack_sbuffer is just a string buffer, we can use our own String type. --- src/nvim/msgpack_rpc/channel.c | 8 ++++---- src/nvim/msgpack_rpc/packer.c | 27 ++++++++++++++++++--------- src/nvim/msgpack_rpc/packer.h | 5 +++++ src/nvim/msgpack_rpc/packer_defs.h | 2 +- 4 files changed, 28 insertions(+), 14 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 6a0dc10214..0930f0c7b3 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -590,16 +590,16 @@ static void packer_buffer_init_channels(Channel **chans, size_t nchans, PackerBu packer->endptr = packer->startptr + ARENA_BLOCK_SIZE; packer->packer_flush = channel_flush_callback; packer->anydata = chans; - packer->anylen = nchans; + packer->anyint = (int64_t)nchans; } static void packer_buffer_finish_channels(PackerBuffer *packer) { size_t len = (size_t)(packer->ptr - packer->startptr); if (len > 0) { - WBuffer *buf = wstream_new_buffer(packer->startptr, len, packer->anylen, free_block); + WBuffer *buf = wstream_new_buffer(packer->startptr, len, (size_t)packer->anyint, free_block); Channel **chans = packer->anydata; - for (size_t i = 0; i < packer->anylen; i++) { + for (int64_t i = 0; i < packer->anyint; i++) { channel_write(chans[i], buf); } } else { @@ -610,7 +610,7 @@ static void packer_buffer_finish_channels(PackerBuffer *packer) static void channel_flush_callback(PackerBuffer *packer) { packer_buffer_finish_channels(packer); - packer_buffer_init_channels(packer->anydata, packer->anylen, packer); + packer_buffer_init_channels(packer->anydata, (size_t)packer->anyint, packer); } void rpc_set_client_info(uint64_t id, Dictionary info) diff --git a/src/nvim/msgpack_rpc/packer.c b/src/nvim/msgpack_rpc/packer.c index 9c0d2910fa..58318b88b0 100644 --- a/src/nvim/msgpack_rpc/packer.c +++ b/src/nvim/msgpack_rpc/packer.c @@ -10,8 +10,7 @@ static void check_buffer(PackerBuffer *packer) { - ptrdiff_t remaining = packer->endptr - packer->ptr; - if (remaining < MPACK_ITEM_SIZE) { + if (mpack_remaining(packer) < MPACK_ITEM_SIZE) { packer->packer_flush(packer); } } @@ -28,15 +27,20 @@ static void mpack_w8(char **b, const char *data) #endif } +void mpack_uint64(char **ptr, uint64_t i) +{ + if (i > 0xfffffff) { + mpack_w(ptr, 0xcf); + mpack_w8(ptr, (char *)&i); + } else { + mpack_uint(ptr, (uint32_t)i); + } +} + void mpack_integer(char **ptr, Integer i) { if (i >= 0) { - if (i > 0xfffffff) { - mpack_w(ptr, 0xcf); - mpack_w8(ptr, (char *)&i); - } else { - mpack_uint(ptr, (uint32_t)i); - } + mpack_uint64(ptr, (uint64_t)i); } else { if (i < -0x80000000LL) { mpack_w(ptr, 0xd3); @@ -80,11 +84,16 @@ void mpack_str(String str, PackerBuffer *packer) abort(); } + mpack_raw(str.data, len, packer); +} + +void mpack_raw(char *data, size_t len, PackerBuffer *packer) +{ size_t pos = 0; while (pos < len) { ptrdiff_t remaining = packer->endptr - packer->ptr; size_t to_copy = MIN(len - pos, (size_t)remaining); - memcpy(packer->ptr, str.data + pos, to_copy); + memcpy(packer->ptr, data + pos, to_copy); packer->ptr += to_copy; pos += to_copy; diff --git a/src/nvim/msgpack_rpc/packer.h b/src/nvim/msgpack_rpc/packer.h index 8117bd09bd..299962bab4 100644 --- a/src/nvim/msgpack_rpc/packer.h +++ b/src/nvim/msgpack_rpc/packer.h @@ -71,6 +71,11 @@ static inline void mpack_map(char **buf, uint32_t len) } } +static inline size_t mpack_remaining(PackerBuffer *packer) +{ + return (size_t)(packer->endptr - packer->ptr); +} + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/packer.h.generated.h" #endif diff --git a/src/nvim/msgpack_rpc/packer_defs.h b/src/nvim/msgpack_rpc/packer_defs.h index 420f3dc424..95d86caaab 100644 --- a/src/nvim/msgpack_rpc/packer_defs.h +++ b/src/nvim/msgpack_rpc/packer_defs.h @@ -19,6 +19,6 @@ struct packer_buffer_t { // these are free to be used by packer_flush for any purpose, if want void *anydata; - size_t anylen; + int64_t anyint; PackerBufferFlush packer_flush; }; -- cgit From 2bb1a18631c4035e4a582b7d995968acbac874bf Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 15 Jun 2024 19:50:44 +0200 Subject: refactor(typval): don't use msgpack_packer for msgpackdump() Step towords completely eliminating msgpack_packer. --- src/nvim/msgpack_rpc/packer.c | 76 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/packer.c b/src/nvim/msgpack_rpc/packer.c index 58318b88b0..279cbb3925 100644 --- a/src/nvim/msgpack_rpc/packer.c +++ b/src/nvim/msgpack_rpc/packer.c @@ -8,7 +8,7 @@ # include "msgpack_rpc/packer.c.generated.h" #endif -static void check_buffer(PackerBuffer *packer) +void mpack_check_buffer(PackerBuffer *packer) { if (mpack_remaining(packer) < MPACK_ITEM_SIZE) { packer->packer_flush(packer); @@ -87,7 +87,25 @@ void mpack_str(String str, PackerBuffer *packer) mpack_raw(str.data, len, packer); } -void mpack_raw(char *data, size_t len, PackerBuffer *packer) +void mpack_bin(const char *data, size_t len, PackerBuffer *packer) +{ + if (len < 0xff) { + mpack_w(&packer->ptr, 0xc4); + mpack_w(&packer->ptr, len); + } else if (len < 0xffff) { + mpack_w(&packer->ptr, 0xc5); + mpack_w2(&packer->ptr, (uint32_t)len); + } else if (len < 0xffffffff) { + mpack_w(&packer->ptr, 0xc6); + mpack_w4(&packer->ptr, (uint32_t)len); + } else { + abort(); + } + + mpack_raw(data, len, packer); +} + +void mpack_raw(const char *data, size_t len, PackerBuffer *packer) { size_t pos = 0; while (pos < len) { @@ -103,6 +121,27 @@ void mpack_raw(char *data, size_t len, PackerBuffer *packer) } } +void mpack_ext(char *buf, size_t len, int8_t type, PackerBuffer *packer) +{ + if (len == 1) { + mpack_w(&packer->ptr, 0xd4); + } else if (len == 2) { + mpack_w(&packer->ptr, 0xd5); + } else if (len <= 0xff) { + mpack_w(&packer->ptr, 0xc7); + } else if (len < 0xffff) { + mpack_w(&packer->ptr, 0xc8); + mpack_w2(&packer->ptr, (uint32_t)len); + } else if (len < 0xffffffff) { + mpack_w(&packer->ptr, 0xc9); + mpack_w4(&packer->ptr, (uint32_t)len); + } else { + abort(); + } + mpack_w(&packer->ptr, type); + mpack_raw(buf, len, packer); +} + void mpack_handle(ObjectType type, handle_T handle, PackerBuffer *packer) { char exttype = (char)(type - EXT_OBJECT_TYPE_SHIFT); @@ -156,7 +195,7 @@ void mpack_object_inner(Object *current, Object *container, size_t container_idx kvi_init(stack); while (true) { - check_buffer(packer); + mpack_check_buffer(packer); switch (current->type) { case kObjectTypeLuaRef: // TODO(bfredl): could also be an error. Though kObjectTypeLuaRef @@ -231,7 +270,7 @@ void mpack_object_inner(Object *current, Object *container, size_t container_idx } else { Dictionary dict = container->data.dictionary; KeyValuePair *it = &dict.items[container_idx++]; - check_buffer(packer); + mpack_check_buffer(packer); mpack_str(it->key, packer); current = &it->value; if (container_idx >= dict.size) { @@ -241,3 +280,32 @@ void mpack_object_inner(Object *current, Object *container, size_t container_idx } kvi_destroy(stack); } + +PackerBuffer packer_string_buffer(void) +{ + const size_t initial_size = 64; // must be larger than SHADA_MPACK_FREE_SPACE + char *alloc = xmalloc(initial_size); + return (PackerBuffer) { + .startptr = alloc, + .ptr = alloc, + .endptr = alloc + initial_size, + .packer_flush = flush_string_buffer, + }; +} + +static void flush_string_buffer(PackerBuffer *buffer) +{ + size_t current_capacity = (size_t)(buffer->endptr - buffer->startptr); + size_t new_capacity = 2 * current_capacity; + size_t len = (size_t)(buffer->ptr - buffer->startptr); + + buffer->startptr = xrealloc(buffer->startptr, new_capacity); + buffer->ptr = buffer->startptr + len; + buffer->endptr = buffer->startptr + new_capacity; +} + +/// can only be used with a PackerBuffer from `packer_string_buffer` +String packer_take_string(PackerBuffer *buffer) +{ + return (String){ .data = buffer->startptr, .size = (size_t)(buffer->ptr - buffer->startptr) }; +} -- cgit From 782b3024ef0e3d6615e9dc90509a29e96ab58152 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 24 Jun 2024 11:27:56 +0200 Subject: refactor(shada): don't use msgpack_packer for shada Now msgpack-c is never used for packing. The real fun part will be replacing it for unpacking. --- src/nvim/msgpack_rpc/packer.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/packer.c b/src/nvim/msgpack_rpc/packer.c index 279cbb3925..4e9e3243a0 100644 --- a/src/nvim/msgpack_rpc/packer.c +++ b/src/nvim/msgpack_rpc/packer.c @@ -10,7 +10,7 @@ void mpack_check_buffer(PackerBuffer *packer) { - if (mpack_remaining(packer) < MPACK_ITEM_SIZE) { + if (mpack_remaining(packer) < 2 * MPACK_ITEM_SIZE) { packer->packer_flush(packer); } } @@ -87,8 +87,9 @@ void mpack_str(String str, PackerBuffer *packer) mpack_raw(str.data, len, packer); } -void mpack_bin(const char *data, size_t len, PackerBuffer *packer) +void mpack_bin(String str, PackerBuffer *packer) { + const size_t len = str.size; if (len < 0xff) { mpack_w(&packer->ptr, 0xc4); mpack_w(&packer->ptr, len); @@ -102,7 +103,7 @@ void mpack_bin(const char *data, size_t len, PackerBuffer *packer) abort(); } - mpack_raw(data, len, packer); + mpack_raw(str.data, len, packer); } void mpack_raw(const char *data, size_t len, PackerBuffer *packer) @@ -119,6 +120,7 @@ void mpack_raw(const char *data, size_t len, PackerBuffer *packer) packer->packer_flush(packer); } } + mpack_check_buffer(packer); } void mpack_ext(char *buf, size_t len, int8_t type, PackerBuffer *packer) -- cgit From f926cc32c9262b6254e2843276b951cef9da1afe Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 2 Jul 2024 13:45:50 +0200 Subject: refactor(shada): rework msgpack decoding without msgpack-c This also makes shada reading slightly faster due to avoiding some copying and allocation. Use keysets to drive decoding of msgpack maps for shada entries. --- src/nvim/msgpack_rpc/channel.c | 3 - src/nvim/msgpack_rpc/channel_defs.h | 1 - src/nvim/msgpack_rpc/unpacker.c | 196 ++++++++++++++++++++++++++++++++++++ src/nvim/msgpack_rpc/unpacker.h | 2 + 4 files changed, 198 insertions(+), 4 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 0930f0c7b3..e4aef4063d 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -1,8 +1,5 @@ #include #include -#include -#include -#include #include #include #include diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h index 7dc1374964..6c8b05b8f3 100644 --- a/src/nvim/msgpack_rpc/channel_defs.h +++ b/src/nvim/msgpack_rpc/channel_defs.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include diff --git a/src/nvim/msgpack_rpc/unpacker.c b/src/nvim/msgpack_rpc/unpacker.c index 28d27e8268..9372754b01 100644 --- a/src/nvim/msgpack_rpc/unpacker.c +++ b/src/nvim/msgpack_rpc/unpacker.c @@ -11,6 +11,7 @@ #include "nvim/memory.h" #include "nvim/msgpack_rpc/channel_defs.h" #include "nvim/msgpack_rpc/unpacker.h" +#include "nvim/strings.h" #include "nvim/ui_client.h" #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -206,6 +207,7 @@ bool unpacker_parse_header(Unpacker *p) assert(!ERROR_SET(&p->unpack_error)); + // TODO(bfredl): eliminate p->reader, we can use mpack_rtoken directly #define NEXT(tok) \ result = mpack_read(&p->reader, &data, &size, &tok); \ if (result) { goto error; } @@ -522,3 +524,197 @@ bool unpacker_parse_redraw(Unpacker *p) abort(); } } + +/// require complete string. safe to use e.g. in shada as we have loaded a complete shada item into +/// a linear buffer. +/// +/// data and size are preserved in cause of failure +/// +/// @return "data" is NULL exact when failure (non-null data and size=0 for +/// valid empty string) +String unpack_string(const char **data, size_t *size) +{ + const char *data2 = *data; + size_t size2 = *size; + mpack_token_t tok; + + // TODO(bfredl): this code is hot a f, specialize! + int result = mpack_rtoken(&data2, &size2, &tok); + if (result || (tok.type != MPACK_TOKEN_STR && tok.type != MPACK_TOKEN_BIN)) { + return (String)STRING_INIT; + } + if (*size < tok.length) { + // result = MPACK_EOF; + return (String)STRING_INIT; + } + (*data) = data2 + tok.length; + (*size) = size2 - tok.length; + return cbuf_as_string((char *)data2, tok.length); +} + +/// @return -1 if not an array or EOF. otherwise size of valid array +ssize_t unpack_array(const char **data, size_t *size) +{ + // TODO(bfredl): this code is hot, specialize! + mpack_token_t tok; + int result = mpack_rtoken(data, size, &tok); + if (result || tok.type != MPACK_TOKEN_ARRAY) { + return -1; + } + return tok.length; +} + +/// does not keep "data" untouched on failure +bool unpack_integer(const char **data, size_t *size, Integer *res) +{ + mpack_token_t tok; + int result = mpack_rtoken(data, size, &tok); + if (result) { + return false; + } + return unpack_uint_or_sint(tok, res); +} + +bool unpack_uint_or_sint(mpack_token_t tok, Integer *res) +{ + if (tok.type == MPACK_TOKEN_UINT) { + *res = (Integer)mpack_unpack_uint(tok); + return true; + } else if (tok.type == MPACK_TOKEN_SINT) { + *res = (Integer)mpack_unpack_sint(tok); + return true; + } + return false; +} + +static void parse_nop(mpack_parser_t *parser, mpack_node_t *node) +{ +} + +int unpack_skip(const char **data, size_t *size) +{ + mpack_parser_t parser; + mpack_parser_init(&parser, 0); + + return mpack_parse(&parser, data, size, parse_nop, parse_nop); +} + +void push_additional_data(AdditionalDataBuilder *ad, const char *data, size_t size) +{ + if (kv_size(*ad) == 0) { + AdditionalData init = { 0 }; + kv_concat_len(*ad, &init, sizeof(init)); + } + AdditionalData *a = (AdditionalData *)ad->items; + a->nitems++; + a->nbytes += (uint32_t)size; + kv_concat_len(*ad, data, size); +} + +// currently only used for shada, so not re-entrant like unpacker_parse_redraw +bool unpack_keydict(void *retval, FieldHashfn hashy, AdditionalDataBuilder *ad, const char **data, + size_t *restrict size, char **error) +{ + OptKeySet *ks = (OptKeySet *)retval; + mpack_token_t tok; + + int result = mpack_rtoken(data, size, &tok); + if (result || tok.type != MPACK_TOKEN_MAP) { + *error = xstrdup("is not a dictionary"); + return false; + } + + size_t map_size = tok.length; + + for (size_t i = 0; i < map_size; i++) { + const char *item_start = *data; + // TODO(bfredl): we could specialize a hot path for FIXSTR here + String key = unpack_string(data, size); + if (!key.data) { + *error = arena_printf(NULL, "has key value which is not a string").data; + return false; + } else if (key.size == 0) { + *error = arena_printf(NULL, "has empty key").data; + return false; + } + KeySetLink *field = hashy(key.data, key.size); + + if (!field) { + int status = unpack_skip(data, size); + if (status) { + return false; + } + + if (ad) { + push_additional_data(ad, item_start, (size_t)(*data - item_start)); + } + continue; + } + + assert(field->opt_index >= 0); + uint64_t flag = (1ULL << field->opt_index); + if (ks->is_set_ & flag) { + *error = xstrdup("duplicate key"); + return false; + } + ks->is_set_ |= flag; + + char *mem = ((char *)retval + field->ptr_off); + switch (field->type) { + case kObjectTypeBoolean: + if (*size == 0 || (**data & 0xfe) != 0xc2) { + *error = arena_printf(NULL, "has %.*s key value which is not a boolean", (int)key.size, + key.data).data; + return false; + } + *(Boolean *)mem = **data & 0x01; + (*data)++; (*size)--; + break; + + case kObjectTypeInteger: + if (!unpack_integer(data, size, (Integer *)mem)) { + *error = arena_printf(NULL, "has %.*s key value which is not an integer", (int)key.size, + key.data).data; + return false; + } + break; + + case kObjectTypeString: { + String val = unpack_string(data, size); + if (!val.data) { + *error = arena_printf(NULL, "has %.*s key value which is not a binary", (int)key.size, + key.data).data; + return false; + } + *(String *)mem = val; + break; + } + + case kUnpackTypeStringArray: { + ssize_t len = unpack_array(data, size); + if (len < 0) { + *error = arena_printf(NULL, "has %.*s key with non-array value", (int)key.size, + key.data).data; + return false; + } + StringArray *a = (StringArray *)mem; + kv_ensure_space(*a, (size_t)len); + for (size_t j = 0; j < (size_t)len; j++) { + String item = unpack_string(data, size); + if (!item.data) { + *error = arena_printf(NULL, "has %.*s array with non-binary value", (int)key.size, + key.data).data; + return false; + } + kv_push(*a, item); + } + break; + } + + default: + abort(); // not supported + } + } + + return true; +} diff --git a/src/nvim/msgpack_rpc/unpacker.h b/src/nvim/msgpack_rpc/unpacker.h index ed55fdd4af..c29462292f 100644 --- a/src/nvim/msgpack_rpc/unpacker.h +++ b/src/nvim/msgpack_rpc/unpacker.h @@ -41,6 +41,8 @@ struct Unpacker { bool has_grid_line_event; }; +typedef kvec_t(char) AdditionalDataBuilder; + // unrecovareble error. unpack_error should be set! #define unpacker_closed(p) ((p)->state < 0) -- cgit From 1247684ae14e83c5b742be390de8dee00fd4e241 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 2 Jul 2024 13:47:04 +0200 Subject: build(deps): remove msgpack-c dependency --- src/nvim/msgpack_rpc/unpacker.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/unpacker.c b/src/nvim/msgpack_rpc/unpacker.c index 9372754b01..efd9a1a11f 100644 --- a/src/nvim/msgpack_rpc/unpacker.c +++ b/src/nvim/msgpack_rpc/unpacker.c @@ -525,12 +525,12 @@ bool unpacker_parse_redraw(Unpacker *p) } } -/// require complete string. safe to use e.g. in shada as we have loaded a complete shada item into -/// a linear buffer. +/// Requires a complete string. safe to use e.g. in shada as we have loaded a +/// complete shada item into a linear buffer. /// -/// data and size are preserved in cause of failure +/// Data and size are preserved in cause of failure. /// -/// @return "data" is NULL exact when failure (non-null data and size=0 for +/// @return "data" is NULL only when failure (non-null data and size=0 for /// valid empty string) String unpack_string(const char **data, size_t *size) { -- cgit From 96128a5076b7e45fc01163151401a9e2acdff565 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 2 Sep 2024 15:57:07 +0200 Subject: feat(startup): validate --listen address Problem: `nvim --listen` does not error on EADDRINUSE. #30123 Solution: Now that `$NVIM_LISTEN_ADDRESS` is deprecated and input *only* (instead of the old, ambiguous situation where it was both an input *and* an output), we can be fail fast instead of trying to "recover". This reverts the "recovery" behavior of 704ba4151e7f67999510ee0ac19fdabb595d530c, but that was basically a workaround for the fragility of `$NVIM_LISTEN_ADDRESS`. --- src/nvim/msgpack_rpc/server.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 24bd343a34..ae34829181 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -28,27 +28,32 @@ static garray_T watchers = GA_EMPTY_INIT_VALUE; #endif /// Initializes the module -bool server_init(const char *listen_addr) +/// +/// @returns 0: success, 1: validation error, 2: already listening, -errno: failed to bind/listen. +int server_init(const char *listen_addr) { + bool must_free = false; ga_init(&watchers, sizeof(SocketWatcher *), 1); // $NVIM_LISTEN_ADDRESS (deprecated) - if (!listen_addr && os_env_exists(ENV_LISTEN)) { + if ((!listen_addr || listen_addr[0] == '\0') && os_env_exists(ENV_LISTEN)) { listen_addr = os_getenv(ENV_LISTEN); } - int rv = listen_addr ? server_start(listen_addr) : 1; - if (0 != rv) { + if (!listen_addr || listen_addr[0] == '\0') { listen_addr = server_address_new(NULL); - if (!listen_addr) { - return false; - } - rv = server_start(listen_addr); - xfree((char *)listen_addr); + must_free = true; + } + + if (!listen_addr) { + abort(); // Cannot happen. } + int rv = server_start(listen_addr); + if (os_env_exists(ENV_LISTEN)) { - // Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. + // Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be + // leaked to child jobs or :terminal. os_unsetenv(ENV_LISTEN); } @@ -57,7 +62,11 @@ bool server_init(const char *listen_addr) ELOG("test log message"); } - return rv == 0; + if (must_free) { + xfree((char *)listen_addr); + } + + return rv; } /// Teardown a single server -- cgit From 08153ddd1c149c867948f4681846531d53ba7759 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 8 Sep 2024 07:07:19 -0700 Subject: fix(startup): ignore broken $XDG_RUNTIME_DIR #30285 Problem: $XDG_RUNTIME_DIR may be broken on WSL, which prevents starting (and even building) Nvim. #30282 Solution: - When startup fails, mention the servername in the error message. - If an autogenerated server address fails, log an error and continue with an empty `v:servername`. It's only fatal if a user provides a bad `--listen` or `$NVIM_LISTEN_ADDRESS` address. Before: $ nvim --headless --listen ./hello.sock nvim: Failed to --listen: "address already in use" $ NVIM_LISTEN_ADDRESS='./hello.sock' ./build/bin/nvim --headless nvim: Failed to --listen: "address already in use" After: $ nvim --headless --listen ./hello.sock nvim: Failed to --listen: address already in use: "./hello.sock" $ NVIM_LISTEN_ADDRESS='./hello.sock' ./build/bin/nvim --headless nvim: Failed $NVIM_LISTEN_ADDRESS: address already in use: "./hello.sock" --- src/nvim/msgpack_rpc/server.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index ae34829181..9cfe46454d 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -11,12 +11,14 @@ #include "nvim/event/socket.h" #include "nvim/garray.h" #include "nvim/garray_defs.h" +#include "nvim/globals.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/memory.h" #include "nvim/msgpack_rpc/server.h" #include "nvim/os/os.h" #include "nvim/os/stdpaths_defs.h" +#include "nvim/types_defs.h" #define MAX_CONNECTIONS 32 #define ENV_LISTEN "NVIM_LISTEN_ADDRESS" // deprecated @@ -27,20 +29,24 @@ static garray_T watchers = GA_EMPTY_INIT_VALUE; # include "msgpack_rpc/server.c.generated.h" #endif -/// Initializes the module +/// Initializes resources, handles `--listen`, starts the primary server at v:servername. /// -/// @returns 0: success, 1: validation error, 2: already listening, -errno: failed to bind/listen. -int server_init(const char *listen_addr) +/// @returns true on success, false on fatal error (message stored in IObuff) +bool server_init(const char *listen_addr) { + bool ok = true; bool must_free = false; + TriState user_arg = kTrue; // User-provided --listen arg. ga_init(&watchers, sizeof(SocketWatcher *), 1); // $NVIM_LISTEN_ADDRESS (deprecated) if ((!listen_addr || listen_addr[0] == '\0') && os_env_exists(ENV_LISTEN)) { + user_arg = kFalse; // User-provided env var. listen_addr = os_getenv(ENV_LISTEN); } if (!listen_addr || listen_addr[0] == '\0') { + user_arg = kNone; // Autogenerated server address. listen_addr = server_address_new(NULL); must_free = true; } @@ -51,12 +57,6 @@ int server_init(const char *listen_addr) int rv = server_start(listen_addr); - if (os_env_exists(ENV_LISTEN)) { - // Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be - // leaked to child jobs or :terminal. - os_unsetenv(ENV_LISTEN); - } - // TODO(justinmk): this is for logging_spec. Can remove this after nvim_log #7062 is merged. if (os_env_exists("__NVIM_TEST_LOG")) { ELOG("test log message"); @@ -66,7 +66,28 @@ int server_init(const char *listen_addr) xfree((char *)listen_addr); } - return rv; + if (rv == 0 || user_arg == kNone) { + // The autogenerated servername can fail if the user has a broken $XDG_RUNTIME_DIR. #30282 + // But that is not fatal (startup will continue, logged in $NVIM_LOGFILE, empty v:servername). + goto end; + } + + (void)snprintf(IObuff, IOSIZE, + user_arg == + kTrue ? "Failed to --listen: %s: \"%s\"" + : "Failed $NVIM_LISTEN_ADDRESS: %s: \"%s\"", + rv < 0 ? os_strerror(rv) : (rv == 1 ? "empty address" : "?"), + listen_addr ? listen_addr : "(empty)"); + ok = false; + +end: + if (os_env_exists(ENV_LISTEN)) { + // Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be + // leaked to child jobs or :terminal. + os_unsetenv(ENV_LISTEN); + } + + return ok; } /// Teardown a single server -- cgit From 8a2aec99748229ad9d1e12c1cbc0768d063e8eed Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 8 Sep 2024 12:48:32 -0700 Subject: fix(startup): server fails if $NVIM_APPNAME is relative dir #30310 Problem: If $NVIM_APPNAME is a relative dir path, Nvim fails to start its primary/default server, and `v:servername` is empty. Root cause is d34c64e342dfba9248d1055e702d02620a1b31a8, but this wasn't noticed until 96128a5076b7 started reporting the error more loudly. Solution: - `server_address_new`: replace slashes "/" in the appname before using it as a servername. - `vim_mktempdir`: always prefer the system-wide top-level "nvim.user/" directory. That isn't intended to be specific to NVIM_APPNAME; rather, each *subdirectory* ("nvim.user/xxx") is owned by each Nvim instance. Nvim "apps" can be identified by the server socket(s) stored in those per-Nvim subdirs. fix #30256 --- src/nvim/msgpack_rpc/server.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 9cfe46454d..dc2b85154f 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -121,14 +121,15 @@ char *server_address_new(const char *name) { static uint32_t count = 0; char fmt[ADDRESS_MAX_SIZE]; - const char *appname = get_appname(); #ifdef MSWIN + (void)get_appname(true); int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32, - name ? name : appname, os_get_pid(), count++); + name ? name : NameBuff, os_get_pid(), count++); #else char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir); + (void)get_appname(true); int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32, - dir, name ? name : appname, os_get_pid(), count++); + dir, name ? name : NameBuff, os_get_pid(), count++); xfree(dir); #endif if ((size_t)r >= sizeof(fmt)) { -- cgit From 648d6426c863c75643d714d45f4b67e19ac6944a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 9 Sep 2024 05:14:47 -0700 Subject: fix(server): CID 509282: DEADCODE #30316 listen_addr cannot be NULL at this point. --- src/nvim/msgpack_rpc/server.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index dc2b85154f..7f26fd35cd 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -51,10 +51,6 @@ bool server_init(const char *listen_addr) must_free = true; } - if (!listen_addr) { - abort(); // Cannot happen. - } - int rv = server_start(listen_addr); // TODO(justinmk): this is for logging_spec. Can remove this after nvim_log #7062 is merged. @@ -77,7 +73,7 @@ bool server_init(const char *listen_addr) kTrue ? "Failed to --listen: %s: \"%s\"" : "Failed $NVIM_LISTEN_ADDRESS: %s: \"%s\"", rv < 0 ? os_strerror(rv) : (rv == 1 ? "empty address" : "?"), - listen_addr ? listen_addr : "(empty)"); + listen_addr); ok = false; end: @@ -118,6 +114,7 @@ void server_teardown(void) /// - Windows: "\\.\pipe\.." /// - Other: "/tmp/nvim.user/xxx/.." char *server_address_new(const char *name) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET { static uint32_t count = 0; char fmt[ADDRESS_MAX_SIZE]; -- cgit From 5d7853f22903a4f42d52f565f6a662c3ef178a8c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 10 Sep 2024 01:14:18 -0700 Subject: refactor(os/input.c): rename os_inchar => input_get #30327 Problem: The name `os_inchar` (from Vim's old `mch_inchar`) is ambiguous: "inchar" sounds like it could be reading or enqueuing (setting) input. Its docstring is also ambiguous. Solution: - Rename `os_inchar` to `input_get`. - Write some mf'ing docstrings. - Add assert() in TRY_READ(). --- src/nvim/msgpack_rpc/channel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.h b/src/nvim/msgpack_rpc/channel.h index ff73a2fc53..abf1ce7bf6 100644 --- a/src/nvim/msgpack_rpc/channel.h +++ b/src/nvim/msgpack_rpc/channel.h @@ -12,7 +12,7 @@ /// HACK: os/input.c drains this queue immediately before blocking for input. /// Events on this queue are async-safe, but they need the resolved state -/// of os_inchar(), so they are processed "just-in-time". +/// of input_get(), so they are processed "just-in-time". EXTERN MultiQueue *ch_before_blocking_events INIT( = NULL); #ifdef INCLUDE_GENERATED_DECLARATIONS -- cgit From 5931f780e0282ad486fa070bb05b3877cc1d44f0 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 11 Sep 2024 17:25:00 -0700 Subject: feat(log): use "ui" as default name for TUI client #30345 The default "session name" for the builtin TUI is "ui". before: INF 2024-09-10T14:57:35.385 hello.sock os_exit:692: Nvim exit: 1 INF 2024-09-10T14:57:35.388 ?.4543 os_exit:692: Nvim exit: 1 after: INF 2024-09-10T14:59:19.919 hello.sock os_exit:692: Nvim exit: 1 INF 2024-09-10T14:59:19.922 ui.5684 os_exit:692: Nvim exit: 1 --- src/nvim/msgpack_rpc/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 7f26fd35cd..462f8397f4 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -53,7 +53,7 @@ bool server_init(const char *listen_addr) int rv = server_start(listen_addr); - // TODO(justinmk): this is for logging_spec. Can remove this after nvim_log #7062 is merged. + // TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged. if (os_env_exists("__NVIM_TEST_LOG")) { ELOG("test log message"); } -- cgit From 057d27a9d6ef0bb2ee5130704c45b9e9197e7c36 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 15 Sep 2024 12:20:58 -0700 Subject: refactor: rename "process" => "proc" #30387 Problem: - "process" is often used as a verb (`multiqueue_process_events`), which is ambiguous for cases where it's used as a topic. - The documented naming convention for processes is "proc". - `:help dev-name-common` - Shorter is better, when it doesn't harm readability or discoverability. Solution: Rename "process" => "proc" in all C symbols and module names. --- src/nvim/msgpack_rpc/channel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index e4aef4063d..8079b32ede 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -14,7 +14,7 @@ #include "nvim/event/defs.h" #include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" -#include "nvim/event/process.h" +#include "nvim/event/proc.h" #include "nvim/event/rstream.h" #include "nvim/event/wstream.h" #include "nvim/globals.h" -- cgit From 737f58e23230ea14f1648ac1fc7f442ea0f8563c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 20 Sep 2024 07:34:50 +0200 Subject: refactor(api)!: rename Dictionary => Dict In the api_info() output: :new|put =map(filter(api_info().functions, '!has_key(v:val,''deprecated_since'')'), 'v:val') ... {'return_type': 'ArrayOf(Integer, 2)', 'name': 'nvim_win_get_position', 'method': v:true, 'parameters': [['Window', 'window']], 'since': 1} The `ArrayOf(Integer, 2)` return type didn't break clients when we added it, which is evidence that clients don't use the `return_type` field, thus renaming Dictionary => Dict in api_info() is not (in practice) a breaking change. --- src/nvim/msgpack_rpc/channel.c | 14 +++++++------- src/nvim/msgpack_rpc/channel_defs.h | 2 +- src/nvim/msgpack_rpc/packer.c | 6 +++--- src/nvim/msgpack_rpc/unpacker.c | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 8079b32ede..626312b666 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -80,7 +80,7 @@ void rpc_start(Channel *channel) rpc->unpacker = xcalloc(1, sizeof *rpc->unpacker); unpacker_init(rpc->unpacker); rpc->next_request_id = 1; - rpc->info = (Dictionary)ARRAY_DICT_INIT; + rpc->info = (Dict)ARRAY_DICT_INIT; kv_init(rpc->call_stack); if (channel->streamtype != kChannelStreamInternal) { @@ -500,7 +500,7 @@ void rpc_free(Channel *channel) xfree(channel->rpc.unpacker); kv_destroy(channel->rpc.call_stack); - api_free_dictionary(channel->rpc.info); + api_free_dict(channel->rpc.info); } static void chan_close_with_error(Channel *channel, char *msg, int loglevel) @@ -610,14 +610,14 @@ static void channel_flush_callback(PackerBuffer *packer) packer_buffer_init_channels(packer->anydata, (size_t)packer->anyint, packer); } -void rpc_set_client_info(uint64_t id, Dictionary info) +void rpc_set_client_info(uint64_t id, Dict info) { Channel *chan = find_rpc_channel(id); if (!chan) { abort(); } - api_free_dictionary(chan->rpc.info); + api_free_dict(chan->rpc.info); chan->rpc.info = info; // Parse "type" on "info" and set "client_type" @@ -641,9 +641,9 @@ void rpc_set_client_info(uint64_t id, Dictionary info) channel_info_changed(chan, false); } -Dictionary rpc_client_info(Channel *chan) +Dict rpc_client_info(Channel *chan) { - return copy_dictionary(chan->rpc.info, NULL); + return copy_dict(chan->rpc.info, NULL); } const char *get_client_info(Channel *chan, const char *key) @@ -652,7 +652,7 @@ const char *get_client_info(Channel *chan, const char *key) if (!chan->is_rpc) { return NULL; } - Dictionary info = chan->rpc.info; + Dict info = chan->rpc.info; for (size_t i = 0; i < info.size; i++) { if (strequal(key, info.items[i].key.data) && info.items[i].value.type == kObjectTypeString) { diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h index 6c8b05b8f3..871d4e615f 100644 --- a/src/nvim/msgpack_rpc/channel_defs.h +++ b/src/nvim/msgpack_rpc/channel_defs.h @@ -40,6 +40,6 @@ typedef struct { Unpacker *unpacker; uint32_t next_request_id; kvec_t(ChannelCallFrame *) call_stack; - Dictionary info; + Dict info; ClientType client_type; } RpcState; diff --git a/src/nvim/msgpack_rpc/packer.c b/src/nvim/msgpack_rpc/packer.c index 4e9e3243a0..b739f7ba28 100644 --- a/src/nvim/msgpack_rpc/packer.c +++ b/src/nvim/msgpack_rpc/packer.c @@ -226,14 +226,14 @@ void mpack_object_inner(Object *current, Object *container, size_t container_idx case kObjectTypeTabpage: mpack_handle(current->type, (handle_T)current->data.integer, packer); break; - case kObjectTypeDictionary: + case kObjectTypeDict: case kObjectTypeArray: {} size_t current_size; if (current->type == kObjectTypeArray) { current_size = current->data.array.size; mpack_array(&packer->ptr, (uint32_t)current_size); } else { - current_size = current->data.dictionary.size; + current_size = current->data.dict.size; mpack_map(&packer->ptr, (uint32_t)current_size); } if (current_size > 0) { @@ -270,7 +270,7 @@ void mpack_object_inner(Object *current, Object *container, size_t container_idx container = NULL; } } else { - Dictionary dict = container->data.dictionary; + Dict dict = container->data.dict; KeyValuePair *it = &dict.items[container_idx++]; mpack_check_buffer(packer); mpack_str(it->key, packer); diff --git a/src/nvim/msgpack_rpc/unpacker.c b/src/nvim/msgpack_rpc/unpacker.c index efd9a1a11f..4ddc41e596 100644 --- a/src/nvim/msgpack_rpc/unpacker.c +++ b/src/nvim/msgpack_rpc/unpacker.c @@ -59,7 +59,7 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node) } case MPACK_TOKEN_MAP: { Object *obj = parent->data[0].p; - KeyValuePair *kv = &kv_A(obj->data.dictionary, parent->pos); + KeyValuePair *kv = &kv_A(obj->data.dict, parent->pos); if (!parent->key_visited) { // TODO(bfredl): when implementing interrupt parse on error, // stop parsing here when node is not a STR/BIN @@ -166,10 +166,10 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node) break; } case MPACK_TOKEN_MAP: { - Dictionary dict = KV_INITIAL_VALUE; + Dict dict = KV_INITIAL_VALUE; kv_fixsize_arena(&p->arena, dict, node->tok.length); kv_size(dict) = node->tok.length; - *result = DICTIONARY_OBJ(dict); + *result = DICT_OBJ(dict); node->data[0].p = result; break; } @@ -620,7 +620,7 @@ bool unpack_keydict(void *retval, FieldHashfn hashy, AdditionalDataBuilder *ad, int result = mpack_rtoken(data, size, &tok); if (result || tok.type != MPACK_TOKEN_MAP) { - *error = xstrdup("is not a dictionary"); + *error = xstrdup("is not a dict"); return false; } -- cgit