diff options
| -rw-r--r-- | init.lua | 2 | ||||
| -rw-r--r-- | parser.lua | 67 | ||||
| -rwxr-xr-x | parser_test.lua | 14 |
3 files changed, 42 insertions, 41 deletions
@@ -1319,7 +1319,7 @@ local function new_ls(ls_conf) initialized = false, id = 0, inflight = {}, - parser = parser.Parser(), + parser = parser.new(), capabilities = {}, -- exported methods of a language server @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Florian Fischer. All rights reserved. +-- Copyright (c) 2021-2024 Florian Fischer. All rights reserved. -- -- This file is part of vis-lspc. -- @@ -18,14 +18,26 @@ -- Note the chunks received may not end with the end of a message. -- In the worst case a data chunk contains two partial messages on at the beginning -- and one at the end -local function add(p, data) - p.data = p.data .. data +--- @module parser +local parser = {} + +local Parser = {} + +function parser.new() + local self = {exp_len = nil, data = '', msgs = {}} + + setmetatable(self, {__index = Parser}) + return self +end + +function Parser:add(data) + self.data = self.data .. data -- we have not seen a complete header in data yet - if not p.exp_len then + if not self.exp_len then -- search for the end of a header -- LSP message format: 'header\r\n\r\nbody' - local header_end, content_start = p.data:find('\r\n\r\n') + local header_end, content_start = self.data:find('\r\n\r\n') -- header is not complete yet -> save data and wait for more if not header_end then @@ -33,55 +45,44 @@ local function add(p, data) end -- got a complete header - local header = p.data:sub(1, header_end) + local header = self.data:sub(1, header_end) -- extract content length from the header - p.exp_len = tonumber(header:match('%d+')) - if not p.exp_len then - return 'invalid header in data: ' .. p.data + self.exp_len = tonumber(header:match('%d+')) + if not self.exp_len then + return 'invalid header in data: ' .. self.data end -- consume header from data - p.data = p.data:sub(content_start + 1) + self.data = self.data:sub(content_start + 1) end - local data_avail = string.len(p.data) + local data_avail = string.len(self.data) -- we have no complete message yet -> await more data - if p.exp_len > data_avail then + if self.exp_len > data_avail then return end - local complete_msg = p.data:sub(1, p.exp_len) - table.insert(p.msgs, complete_msg) + local complete_msg = self.data:sub(1, self.exp_len) + table.insert(self.msgs, complete_msg) -- consume complete_msg from data - p.data = p.data:sub(p.exp_len + 1) + self.data = self.data:sub(self.exp_len + 1) - local leftover = data_avail - p.exp_len + local leftover = data_avail - self.exp_len -- reset exp_len to search for a new header - p.exp_len = nil + self.exp_len = nil if leftover > 0 then - return p:add('') + return self:add('') end end -local function get_msgs(p) - local msgs = p.msgs - p.msgs = {} +function Parser:get_msgs() + local msgs = self.msgs + self.msgs = {} return msgs end -local function Parser() - local parser = { - add = add, - get_msgs = get_msgs, - exp_len = nil, - data = '', - msgs = {}, - } - return parser -end - -return {Parser = Parser} +return parser diff --git a/parser_test.lua b/parser_test.lua index 4f887f2..28f3d0f 100755 --- a/parser_test.lua +++ b/parser_test.lua @@ -10,7 +10,7 @@ local lunatest = require('lunatest') function test_complete_msg() -- luacheck: ignore 111 local msg = build_msg('foo') - local p = parser.Parser() + local p = parser.new() local err = p:add(msg) lunatest.assert_nil(err) @@ -21,7 +21,7 @@ function test_complete_msg() -- luacheck: ignore 111 end function test_two_complete_msgs() -- luacheck: ignore 111 - local p = parser.Parser() + local p = parser.new() local data = build_msg('foo') local err = p:add(data) lunatest.assert_nil(err) @@ -42,7 +42,7 @@ end function test_two_complete_msgs_at_once() -- luacheck: ignore 111 local data = build_msg('foo') .. build_msg('bar') - local p = parser.Parser() + local p = parser.new() local err = p:add(data) lunatest.assert_nil(err) @@ -57,7 +57,7 @@ function test_split_msg() -- luacheck: ignore 111 local msg = build_msg('foo') local part1 = msg:sub(1, -3) local part2 = msg:sub(-2) - local p = parser.Parser() + local p = parser.new() local err = p:add(part1) lunatest.assert_nil(err) @@ -74,7 +74,7 @@ function test_complete_and_split_msg() -- luacheck: ignore 111 local msg = build_msg('foo') .. build_msg('bar') local part1 = msg:sub(1, -3) local part2 = msg:sub(-2) - local p = parser.Parser() + local p = parser.new() local err = p:add(part1) lunatest.assert_nil(err) @@ -92,7 +92,7 @@ function test_split_hdr() -- luacheck: ignore 111 local msg = build_msg('foo') local part1 = msg:sub(1, 3) local part2 = msg:sub(4) - local p = parser.Parser() + local p = parser.new() local err = p:add(part1) lunatest.assert_nil(err) @@ -109,7 +109,7 @@ function test_split_hdr_body_sep() -- luacheck: ignore 111 local msg = build_msg('foo') local part1 = msg:sub(1, 19) local part2 = msg:sub(20) - local p = parser.Parser() + local p = parser.new() local err = p:add(part1) lunatest.assert_nil(err) |
