-
Notifications
You must be signed in to change notification settings - Fork 0
/
netstrings.go
103 lines (93 loc) · 1.66 KB
/
netstrings.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package netstrings
import (
"bufio"
"bytes"
"io"
"strconv"
"strings"
)
const (
lengthDelim byte = ':'
dataDelim byte = ','
)
type Reader struct {
r *bufio.Reader
}
func NewReader(r io.Reader) *Reader {
return &Reader{r: bufio.NewReader(r)}
}
func (r *Reader) ReadNetstring() ([]byte, error) {
length, err := r.r.ReadBytes(lengthDelim)
if err != nil {
return nil, err
}
l, err := strconv.Atoi(strings.TrimSuffix(string(length), string(lengthDelim)))
if err != nil {
return nil, err
}
ret := make([]byte, l)
_, err = io.ReadFull(r.r, ret)
if err != nil {
return nil, err
}
next, err := r.r.ReadByte()
if err != nil && err != io.EOF {
return nil, err
}
if next != dataDelim {
r.r.UnreadByte()
}
return ret, nil
}
func Decode(in []byte) ([][]byte, error) {
rd := NewReader(bytes.NewReader(in))
ret := make([][]byte, 0)
for {
d, err := rd.ReadNetstring()
if err != nil {
if err == io.EOF {
break
} else {
return nil, err
}
}
ret = append(ret, d)
}
return ret, nil
}
type Writer struct {
w io.Writer
}
func NewWriter(w io.Writer) *Writer {
return &Writer{w: w}
}
func (w *Writer) WriteNetstring(b []byte) error {
_, err := w.w.Write([]byte(strconv.Itoa(len(b))))
if err != nil {
return err
}
_, err = w.w.Write([]byte{lengthDelim})
if err != nil {
return err
}
_, err = w.w.Write(b)
if err != nil {
return err
}
_, err = w.w.Write([]byte{dataDelim})
if err != nil {
return err
}
return nil
}
func Encode(in ...[]byte) ([]byte, error) {
var buf bytes.Buffer
wr := NewWriter(&buf)
for _, d := range in {
err := wr.WriteNetstring(d)
if err != nil {
return nil, err
}
}
return buf.Bytes(), nil
}