-
Notifications
You must be signed in to change notification settings - Fork 1
/
writer.go
117 lines (110 loc) · 2.12 KB
/
writer.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
package gosc
import (
"bufio"
"bytes"
"encoding/binary"
"fmt"
"reflect"
"strings"
)
func writePackage(pack Package, w *bufio.Writer) error {
switch v := pack.(type) {
case *Message:
err := writePaddedString(w, v.Address)
if err != nil {
return err
}
err = writeArguments(w, v.Arguments)
if err != nil {
return err
}
case *Bundle:
if v.Name == "" {
v.Name = "#bundle"
}
err := writePaddedString(w, v.Name)
if err != nil {
return err
}
_, err = timeTagWriter(w, v.Timetag)
if err != nil {
return err
}
for _, msg := range v.Messages {
err = writePayload(w, msg)
if err != nil {
return err
}
}
for _, bundle := range v.Bundles {
err = writePayload(w, bundle)
if err != nil {
return err
}
}
default:
return fmt.Errorf("unknown package type (%v)", pack)
}
return nil
}
func writePayload(w *bufio.Writer, pack Package) error {
buf := bytes.Buffer{}
bufW := bufio.NewWriter(&buf)
err := writePackage(pack, bufW)
if err != nil {
return err
}
_ = bufW.Flush()
data := buf.Bytes()
if err := binary.Write(w, binary.BigEndian, uint32(len(data))); err != nil {
return err
}
_, err = w.Write(data)
if err != nil {
return err
}
return nil
}
func writeArguments(w *bufio.Writer, arguments []any) error {
buf := bytes.Buffer{}
bufWriter := bufio.NewWriter(&buf)
ttString := strings.Builder{}
_, _ = ttString.WriteRune(',')
for _, a := range arguments {
typ := reflect.TypeOf(a)
if writer, ok := writerMap[typ]; ok {
tt, err := writer(bufWriter, a)
if err != nil {
return err
}
if err := ttString.WriteByte(byte(tt)); err != nil {
return err
}
}
}
err := writePaddedString(w, ttString.String())
if err != nil {
return err
}
_ = bufWriter.Flush()
_, err = w.Write(buf.Bytes())
if err != nil {
return err
}
return nil
}
func writePaddedString(w *bufio.Writer, str string) error {
if !strings.HasSuffix(str, "\x00") {
str += "\x00"
}
_, err := w.WriteString(str)
if err != nil {
return err
}
padding := make([]byte, getPadBytes(len(str)))
_, err = w.Write(padding)
if err != nil {
return err
}
return nil
}