diff options
| author | fischerling <github@muhq.space> | 2021-08-16 14:10:48 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-16 14:10:48 +0200 |
| commit | c63d31c899c347021744502cd9b245ade5096de4 (patch) | |
| tree | 26afb1bdd77762d67b3803c8068eab5f9cbdf5a5 /parser.lua | |
| parent | bcab92186e8bd66e6841f33275d261af00e43a25 (diff) | |
| parent | 29b50c08a7e8524797549354a2e5063974c0e1b2 (diff) | |
| download | vis-lspc-c63d31c899c347021744502cd9b245ade5096de4.tar.gz vis-lspc-c63d31c899c347021744502cd9b245ade5096de4.zip | |
Merge pull request #17 from fischerling/parser
Improve message parsing
Diffstat (limited to 'parser.lua')
| -rw-r--r-- | parser.lua | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/parser.lua b/parser.lua new file mode 100644 index 0000000..f1b09f5 --- /dev/null +++ b/parser.lua @@ -0,0 +1,75 @@ +-- Copyright (c) 2021 Florian Fischer. All rights reserved. +-- Use of this source code is governed by a MIT license found in the LICENSE file. + +-- Parse the data send by a language server +-- 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 + + -- we have not seen a complete header in data yet + if not p.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') + + -- header is not complete yet -> save data and wait for more + if not header_end then + return + end + + -- got a complete header + local header = p.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 + end + + -- consume header from data + p.data = p.data:sub(content_start + 1) + end + + local data_avail = string.len(p.data) + -- we have no complete message yet -> await more data + if p.exp_len > data_avail then + return + end + + local complete_msg = p.data:sub(1, p.exp_len) + table.insert(p.msgs, complete_msg) + + -- consume complete_msg from data + p.data = p.data:sub(p.exp_len + 1) + + local leftover = data_avail - p.exp_len + + -- reset exp_len to search for a new header + p.exp_len = nil + + if leftover > 0 then + return p:add('') + end +end + +local function get_msgs(p) + local msgs = p.msgs + p.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} |
