// JSON-RPC protocol helpers for LSP communication over stdin/stdout. // Reads Content-Length framed messages from stdin, writes to stdout. var fd = use('fd') var json = use('json') // Read a single JSON-RPC message from stdin. // Protocol: "Content-Length: N\r\n\r\n" followed by N bytes of JSON. var read_message = function() { var header = "" var ch = null var content_length = null var body = null var total = 0 var chunk = null // Read header byte by byte until we hit \r\n\r\n while (true) { ch = fd.read(0, 1) if (ch == null) { return null } header = header + text(ch) if (ends_with(header, "\r\n\r\n")) { break } } // Parse Content-Length from header var lines = array(header, "\r\n") var _i = 0 while (_i < length(lines)) { if (starts_with(lines[_i], "Content-Length:")) { content_length = number(trim(text(lines[_i], 16))) } _i = _i + 1 } if (content_length == null) { return null } // Read exactly content_length bytes body = "" total = 0 while (total < content_length) { chunk = fd.read(0, content_length - total) if (chunk == null) { return null } chunk = text(chunk) body = body + chunk total = total + length(chunk) } return json.decode(body) } // Send a JSON-RPC message to stdout. var send_message = function(msg) { var body = json.encode(msg) var header = `Content-Length: ${text(length(body))}\r\n\r\n` fd.write(1, header + body) } // Send a JSON-RPC response for a request. var respond = function(id, result) { send_message({ jsonrpc: "2.0", id: id, result: result }) } // Send a JSON-RPC error response. var respond_error = function(id, code, message) { send_message({ jsonrpc: "2.0", id: id, error: { code: code, message: message } }) } // Send a JSON-RPC notification (no id). var notify = function(method, params) { send_message({ jsonrpc: "2.0", method: method, params: params }) } return { read_message: read_message, send_message: send_message, respond: respond, respond_error: respond_error, notify: notify }