Skip to content

Commit ed4a612

Browse files
committed
stream: switch to golang/x/tools lsp stream
1 parent c8ee79c commit ed4a612

File tree

1 file changed

+55
-13
lines changed

1 file changed

+55
-13
lines changed

stream.go

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55
package jsonrpc2
66

77
import (
8+
"bufio"
89
"context"
10+
"fmt"
911
"io"
12+
"strconv"
13+
"strings"
1014
"sync"
1115

12-
"github.com/francoispqt/gojay"
16+
"golang.org/x/xerrors"
1317
)
1418

1519
// Stream abstracts the transport mechanics from the JSON RPC protocol.
@@ -20,31 +24,65 @@ type Stream interface {
2024
Write(context.Context, []byte) error
2125
}
2226

27+
type stream struct {
28+
in *bufio.Reader
29+
out io.Writer
30+
sync.Mutex
31+
}
32+
2333
func NewStream(in io.Reader, out io.Writer) Stream {
2434
return &stream{
25-
in: gojay.BorrowDecoder(in),
35+
in: bufio.NewReader(in),
2636
out: out,
2737
}
2838
}
2939

30-
type stream struct {
31-
in *gojay.Decoder
32-
sync.Mutex
33-
out io.Writer
34-
}
35-
3640
func (s *stream) Read(ctx context.Context) ([]byte, error) {
3741
select {
3842
case <-ctx.Done():
3943
return nil, ctx.Err()
4044
default:
4145
}
4246

43-
defer s.in.Release()
47+
var length int64
48+
for {
49+
line, err := s.in.ReadString('\n')
50+
if err != nil {
51+
return nil, xerrors.Errorf("failed reading header line: %w", err)
52+
}
4453

45-
var data []byte
46-
if err := s.in.Decode(&data); err != nil {
47-
return nil, err
54+
line = strings.TrimSpace(line)
55+
if line == "" { // check we have a header line
56+
break
57+
}
58+
59+
colon := strings.IndexRune(line, ':')
60+
if colon < 0 {
61+
return nil, xerrors.Errorf("invalid header line: %q", line)
62+
}
63+
64+
name, value := line[:colon], strings.TrimSpace(line[colon+1:])
65+
switch name {
66+
case "Content-Length":
67+
if length, err = strconv.ParseInt(value, 10, 32); err != nil {
68+
return nil, xerrors.Errorf("failed parsing Content-Length: %v", value)
69+
}
70+
71+
if length <= 0 {
72+
return nil, xerrors.Errorf("invalid Content-Length: %v", length)
73+
}
74+
default:
75+
// ignoring unknown headers
76+
}
77+
}
78+
79+
if length == 0 {
80+
return nil, xerrors.New("missing Content-Length header")
81+
}
82+
83+
data := make([]byte, length)
84+
if _, err := io.ReadFull(s.in, data); err != nil {
85+
return nil, xerrors.Errorf("failed reading data: %w", err)
4886
}
4987

5088
return data, nil
@@ -56,8 +94,12 @@ func (s *stream) Write(ctx context.Context, data []byte) error {
5694
return ctx.Err()
5795
default:
5896
}
97+
5998
s.Lock()
60-
_, err := s.out.Write(data)
99+
_, err := fmt.Fprintf(s.out, "Content-Length: %v\r\n\r\n", len(data))
100+
if err == nil {
101+
_, err = s.out.Write(data)
102+
}
61103
s.Unlock()
62104

63105
return err

0 commit comments

Comments
 (0)