-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprimitives.go
130 lines (115 loc) · 2.76 KB
/
primitives.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
129
130
package avrogo
import (
"encoding/binary"
"fmt"
"io"
"os"
)
type primitive struct {
id string
reader func(r io.Reader) (o interface{}, err os.Error)
}
func (p primitive) Read(r io.Reader) (interface{}, os.Error) {
return p.reader(r)
}
func readNull(r io.Reader) (interface{}, os.Error) {
return nil, nil
}
func readBoolean(r io.Reader) (o interface{}, err os.Error) {
p := make([]byte, 1)
if _, readerr := io.ReadFull(r, p); readerr != nil {
err = readerr
} else if p[0] == 1 {
o = true
} else if p[0] == 0 {
o = false
} else {
err = os.NewError(fmt.Sprintf("Invalid bool value: 0x%x", p[0]))
}
return
}
func readInt(r io.Reader) (o interface{}, err os.Error) {
p := make([]byte, 1)
x := uint32(0)
for shift := uint(0); ; shift += 7 {
if shift >= 32 {
return nil, os.NewError("int too long!")
} else if _, readerr := io.ReadFull(r, p); readerr != nil {
return nil, readerr
}
b := uint32(p[0])
x |= (b & 0x7F) << shift
if (b & 0x80) == 0 {
break
}
}
return int32((x >> 1) ^ uint32((int32(x&1)<<31)>>31)), nil
}
func readLong(r io.Reader) (int64, os.Error) {
p := make([]byte, 1)
x := uint64(0)
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, os.NewError("long too long!")
} else if _, readerr := io.ReadFull(r, p); readerr != nil {
return 0, readerr
}
b := uint64(p[0])
x |= (b & 0x7F) << shift
if (b & 0x80) == 0 {
break
}
}
return int64((x >> 1) ^ uint64((int64(x&1)<<63)>>63)), nil
}
func readILong(r io.Reader) (interface{}, os.Error) {
return readLong(r)
}
func readFloat(r io.Reader) (interface{}, os.Error) {
var f float32
err := binary.Read(r, binary.LittleEndian, &f)
return f, err
}
func readDouble(r io.Reader) (interface{}, os.Error) {
var d float64
err := binary.Read(r, binary.LittleEndian, &d)
return d, err
}
func readBytes(r io.Reader) (interface{}, os.Error) {
l, err := readLong(r)
if err != nil {
return nil, err
}
b := make([]byte, int32(l))
_, err = io.ReadFull(r, b)
if err != nil {
return nil, err
}
return b, nil
}
func readString(r io.Reader) (string, os.Error) {
buf, err := readBytes(r)
if err != nil {
return "", err
}
return string(buf.([]byte)), nil
}
func readIString(r io.Reader) (interface{}, os.Error) {
return readString(r)
}
var (
primitives = map[string]Type{}
Null = primitive{"null", readNull}
Boolean = primitive{"boolean", readBoolean}
Int = primitive{"int", readInt}
Long = primitive{"long", readILong}
Float = primitive{"float", readFloat}
Double = primitive{"double", readDouble}
Bytes = primitive{"bytes", readBytes}
String = primitive{"string", readIString}
)
func init() {
for _, t := range []primitive{Null, Boolean, Int, Long, Float, Double, Bytes, String} {
primitives[t.id] = t
}
}