/
reader.go
128 lines (111 loc) · 2.66 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
122
123
124
125
126
127
128
package signature
import (
"bytes"
"fmt"
"io"
"github.com/lugu/qiloop/type/basic"
)
// TypeReader reads from r the bytes representing the type
type TypeReader interface {
Read(r io.Reader) ([]byte, error)
}
// constReader is a Reader which always read a constant size.
type constReader int
func (c constReader) Read(r io.Reader) ([]byte, error) {
data := make([]byte, int(c))
err := basic.ReadN(r, data, int(c))
if err != nil {
return nil, err
}
return data, nil
}
type stringReader struct{}
func (v stringReader) Read(r io.Reader) ([]byte, error) {
str, err := basic.ReadString(r)
var buf bytes.Buffer
err = basic.WriteString(str, &buf)
return buf.Bytes(), err
}
// UnknownReader is a TypeReader which returns an error.
type UnknownReader string
func (v UnknownReader) Read(r io.Reader) ([]byte, error) {
return nil, fmt.Errorf("Unknown type '%v'", v)
}
type valueReader struct{}
func (v valueReader) Read(r io.Reader) ([]byte, error) {
sig, err := basic.ReadString(r)
if err != nil {
return nil, fmt.Errorf("read signature: %s", err)
}
reader, err := MakeReader(sig)
if err != nil {
return nil, err
}
data, err := reader.Read(r)
if err != nil {
return nil, fmt.Errorf("read value: %s", err)
}
return append([]byte(sig), data...), err
}
type varReader struct {
reader TypeReader
}
func (v varReader) Read(r io.Reader) ([]byte, error) {
size, err := basic.ReadUint32(r)
if err != nil {
return nil, fmt.Errorf("read size: %s", err)
}
if int(size) < 0 {
return nil, fmt.Errorf("invalid size: %d", size)
}
var buf bytes.Buffer
err = basic.WriteUint32(size, &buf)
if err != nil {
return nil, fmt.Errorf("write size %d: %s",
size, err)
}
for i := 0; i < int(size); i++ {
data, err := v.reader.Read(r)
if err != nil {
return nil, fmt.Errorf("read %d/%d: %s",
i+1, size, err)
}
err = basic.WriteN(&buf, data, len(data))
if err != nil {
return nil, fmt.Errorf("read %d/%d: %s",
i, size, err)
}
}
return buf.Bytes(), nil
}
type memberReader struct {
name string
reader TypeReader
}
type tupleReader []memberReader
func (v tupleReader) Read(r io.Reader) ([]byte, error) {
var buf bytes.Buffer
for _, member := range v {
name := member.name
reader := member.reader
data, err := reader.Read(r)
if err != nil {
return nil, fmt.Errorf("read %s: %s",
name, err)
}
basic.WriteN(&buf, data, len(data))
if err != nil {
return nil, fmt.Errorf("write %s: %s",
name, err)
}
}
return buf.Bytes(), nil
}
// MakeReader parse the signature and returns its associated Reader.
func MakeReader(sig string) (TypeReader, error) {
t, err := Parse(sig)
if err != nil {
return nil, err
}
return t.Reader(), nil
}