aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua')
-rw-r--r--runtime/lua/vim/lsp/rpc.lua34
1 files changed, 21 insertions, 13 deletions
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 7d85be89c9..6739073cd3 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -191,22 +191,30 @@ local default_dispatchers = {
}
--- @async
-local function request_parser_loop()
- local buf = strbuffer.new()
+local function parse_content_length()
+ local strbuf = strbuffer.new()
while true do
- local msg = buf:tostring()
- local header_end = msg:find('\r\n\r\n', 1, true)
- if header_end then
- local header = buf:get(header_end + 1)
- buf:skip(2) -- skip past header boundary
+ local header_len ---@type integer?
+ local ptr, len = strbuf:ref()
+ for i = 0, len - 4 do
+ -- Find the header boundary "\r\n\r\n"
+ -- (compare bytes instead of string.find(), to avoid a string alloc).
+ if ptr[i] == 13 and ptr[i + 1] == 10 and ptr[i + 2] == 13 and ptr[i + 3] == 10 then
+ header_len = i + 2
+ break
+ end
+ end
+ if header_len then
+ local header = strbuf:get(header_len)
+ strbuf:skip(2) -- skip past header boundary
local content_length = get_content_length(header)
- while strbuffer.len(buf) < content_length do
- buf:put(coroutine.yield())
+ while strbuffer.len(strbuf) < content_length do
+ strbuf:put(coroutine.yield())
end
- local body = buf:get(content_length)
- buf:put(coroutine.yield(body))
+ local body = strbuf:get(content_length)
+ strbuf:put(coroutine.yield(body))
else
- buf:put(coroutine.yield())
+ strbuf:put(coroutine.yield())
end
end
end
@@ -218,7 +226,7 @@ end
function M.create_read_loop(handle_body, on_exit, on_error)
on_exit = on_exit or function() end
on_error = on_error or function() end
- local co = coroutine.create(request_parser_loop)
+ local co = coroutine.create(parse_content_length)
coroutine.resume(co)
return function(err, chunk)
if err then