-
Notifications
You must be signed in to change notification settings - Fork 1
/
reader.go
121 lines (111 loc) · 2.38 KB
/
reader.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package gosc
import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
)
func readPackage(r *bufio.Reader) (pack Package, err error) {
firstByte, err := r.Peek(1)
if err != nil {
return nil, err
}
if firstByte[0] == '/' {
pack, err = readMessage(r)
} else if firstByte[0] == '#' {
pack, err = readBundle(r)
}
return
}
func readBundle(r *bufio.Reader) (bundle *Bundle, err error) {
name, err := readPaddedString(r)
if err != nil {
return nil, err
}
tt, err := timeTagReader(r)
if err != nil {
return nil, err
}
bundle = &Bundle{
Timetag: tt.(Timetag),
Messages: make([]*Message, 0, 10),
Bundles: make([]*Bundle, 0, 10),
Name: name,
}
for {
length := int32(0)
if err := binary.Read(r, binary.BigEndian, &length); err == io.EOF {
return bundle, nil
} else if err != nil {
return nil, err
}
buf := make([]byte, length)
bufR := bufio.NewReader(bytes.NewReader(buf))
_, err = io.ReadFull(r, buf)
if err != nil {
return nil, err
}
pack, err := readPackage(bufR)
if err != nil {
return nil, err
}
if pack.GetType() == PackageTypeMessage {
bundle.Messages = append(bundle.Messages, pack.(*Message))
} else if pack.GetType() == PackageTypeBundle {
bundle.Bundles = append(bundle.Bundles, pack.(*Bundle))
} else {
return nil, errors.New("bundle contained unknown type")
}
}
}
func readMessage(r *bufio.Reader) (msg *Message, err error) {
address, err := readPaddedString(r)
if err != nil {
return nil, err
}
args, err := readArguments(r)
if err != nil {
return nil, err
}
return &Message{
Address: address,
Arguments: args,
}, nil
}
func readPaddedString(r *bufio.Reader) (str string, err error) {
str, err = r.ReadString(0)
if err != nil {
return "", err
}
_, err = r.Discard(getPadBytes(len(str)))
if err != nil {
return "", err
}
str = str[:len(str)-1]
return str, nil
}
func readArguments(r *bufio.Reader) ([]any, error) {
typeTags, err := readPaddedString(r)
if err != nil {
return nil, err
}
if typeTags[0] != ',' {
return nil, errors.New("typetag format error")
}
typeTags = typeTags[1:]
res := make([]any, 0, len(typeTags))
for _, tt := range typeTags {
decoder, ok := readerMap[typeTag(tt)]
if !ok {
return nil, fmt.Errorf("unknown tag type '%s'", string(tt))
}
val, err := decoder(r)
if err != nil {
return nil, err
}
res = append(res, val)
}
return res, nil
}