X-Git-Url: https://git.josue.xyz/?p=dotfiles%2F.git;a=blobdiff_plain;f=.config%2Fcoc%2Fextensions%2Fcoc-go-data%2Ftools%2Fpkg%2Fmod%2Fgolang.org%2Fx%2Ftools%40v0.1.1-0.20210319172145-bda8f5cee399%2Finternal%2Fjsonrpc2%2Fstream.go;fp=.config%2Fcoc%2Fextensions%2Fcoc-go-data%2Ftools%2Fpkg%2Fmod%2Fgolang.org%2Fx%2Ftools%40v0.1.1-0.20210319172145-bda8f5cee399%2Finternal%2Fjsonrpc2%2Fstream.go;h=b22be7ee3cd6d1854abe51b35912cf8f975ad032;hp=0000000000000000000000000000000000000000;hb=3c06164f15bd10aed7d66b6314764a2961a14762;hpb=0e9c3ceb40901f4d44981c1376cb9e23a248e006 diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/internal/jsonrpc2/stream.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/internal/jsonrpc2/stream.go new file mode 100644 index 00000000..b22be7ee --- /dev/null +++ b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/internal/jsonrpc2/stream.go @@ -0,0 +1,170 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package jsonrpc2 + +import ( + "bufio" + "context" + "encoding/json" + "fmt" + "io" + "net" + "strconv" + "strings" +) + +// Stream abstracts the transport mechanics from the JSON RPC protocol. +// A Conn reads and writes messages using the stream it was provided on +// construction, and assumes that each call to Read or Write fully transfers +// a single message, or returns an error. +// A stream is not safe for concurrent use, it is expected it will be used by +// a single Conn in a safe manner. +type Stream interface { + // Read gets the next message from the stream. + Read(context.Context) (Message, int64, error) + // Write sends a message to the stream. + Write(context.Context, Message) (int64, error) + // Close closes the connection. + // Any blocked Read or Write operations will be unblocked and return errors. + Close() error +} + +// Framer wraps a network connection up into a Stream. +// It is responsible for the framing and encoding of messages into wire form. +// NewRawStream and NewHeaderStream are implementations of a Framer. +type Framer func(conn net.Conn) Stream + +// NewRawStream returns a Stream built on top of a net.Conn. +// The messages are sent with no wrapping, and rely on json decode consistency +// to determine message boundaries. +func NewRawStream(conn net.Conn) Stream { + return &rawStream{ + conn: conn, + in: json.NewDecoder(conn), + } +} + +type rawStream struct { + conn net.Conn + in *json.Decoder +} + +func (s *rawStream) Read(ctx context.Context) (Message, int64, error) { + select { + case <-ctx.Done(): + return nil, 0, ctx.Err() + default: + } + var raw json.RawMessage + if err := s.in.Decode(&raw); err != nil { + return nil, 0, err + } + msg, err := DecodeMessage(raw) + return msg, int64(len(raw)), err +} + +func (s *rawStream) Write(ctx context.Context, msg Message) (int64, error) { + select { + case <-ctx.Done(): + return 0, ctx.Err() + default: + } + data, err := json.Marshal(msg) + if err != nil { + return 0, fmt.Errorf("marshaling message: %v", err) + } + n, err := s.conn.Write(data) + return int64(n), err +} + +func (s *rawStream) Close() error { + return s.conn.Close() +} + +// NewHeaderStream returns a Stream built on top of a net.Conn. +// The messages are sent with HTTP content length and MIME type headers. +// This is the format used by LSP and others. +func NewHeaderStream(conn net.Conn) Stream { + return &headerStream{ + conn: conn, + in: bufio.NewReader(conn), + } +} + +type headerStream struct { + conn net.Conn + in *bufio.Reader +} + +func (s *headerStream) Read(ctx context.Context) (Message, int64, error) { + select { + case <-ctx.Done(): + return nil, 0, ctx.Err() + default: + } + var total, length int64 + // read the header, stop on the first empty line + for { + line, err := s.in.ReadString('\n') + total += int64(len(line)) + if err != nil { + return nil, total, fmt.Errorf("failed reading header line: %w", err) + } + line = strings.TrimSpace(line) + // check we have a header line + if line == "" { + break + } + colon := strings.IndexRune(line, ':') + if colon < 0 { + return nil, total, fmt.Errorf("invalid header line %q", line) + } + name, value := line[:colon], strings.TrimSpace(line[colon+1:]) + switch name { + case "Content-Length": + if length, err = strconv.ParseInt(value, 10, 32); err != nil { + return nil, total, fmt.Errorf("failed parsing Content-Length: %v", value) + } + if length <= 0 { + return nil, total, fmt.Errorf("invalid Content-Length: %v", length) + } + default: + // ignoring unknown headers + } + } + if length == 0 { + return nil, total, fmt.Errorf("missing Content-Length header") + } + data := make([]byte, length) + if _, err := io.ReadFull(s.in, data); err != nil { + return nil, total, err + } + total += length + msg, err := DecodeMessage(data) + return msg, total, err +} + +func (s *headerStream) Write(ctx context.Context, msg Message) (int64, error) { + select { + case <-ctx.Done(): + return 0, ctx.Err() + default: + } + data, err := json.Marshal(msg) + if err != nil { + return 0, fmt.Errorf("marshaling message: %v", err) + } + n, err := fmt.Fprintf(s.conn, "Content-Length: %v\r\n\r\n", len(data)) + total := int64(n) + if err == nil { + n, err = s.conn.Write(data) + total += int64(n) + } + return total, err +} + +func (s *headerStream) Close() error { + return s.conn.Close() +}