-
Notifications
You must be signed in to change notification settings - Fork 95
/
unmarshal.go
160 lines (130 loc) · 3.39 KB
/
unmarshal.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package rm
import (
"bytes"
"encoding/binary"
"fmt"
)
// UnmarshalBinary implements encoding.UnmarshalBinary for
// transforming bytes into a Rm page
func (rm *Rm) UnmarshalBinary(data []byte) error {
r := newReader(data)
if err := r.checkHeader(); err != nil {
return err
}
rm.Version = r.version
nbLayers, err := r.readNumber()
if err != nil {
return err
}
rm.Layers = make([]Layer, nbLayers)
for i := uint32(0); i < nbLayers; i++ {
nbLines, err := r.readNumber()
if err != nil {
return err
}
rm.Layers[i].Lines = make([]Line, nbLines)
for j := uint32(0); j < nbLines; j++ {
line, err := r.readLine()
if err != nil {
return err
}
rm.Layers[i].Lines[j] = line
}
}
return nil
}
type reader struct {
bytes.Reader
version Version
}
func newReader(data []byte) reader {
br := bytes.NewReader(data)
// we set V5 as default but the real value is
// analysed when checking the header
return reader{*br, V5}
}
func (r *reader) checkHeader() error {
buf := make([]byte, HeaderLen)
n, err := r.Read(buf)
if err != nil {
return err
}
if n != HeaderLen {
return fmt.Errorf("Wrong header size")
}
switch string(buf) {
case HeaderV5:
r.version = V5
case HeaderV3:
r.version = V3
default:
return fmt.Errorf("Unknown header")
}
return nil
}
func (r *reader) readNumber() (uint32, error) {
var nb uint32
if err := binary.Read(r, binary.LittleEndian, &nb); err != nil {
return 0, fmt.Errorf("Wrong number read")
}
return nb, nil
}
func (r *reader) readLine() (Line, error) {
var line Line
if err := binary.Read(r, binary.LittleEndian, &line.BrushType); err != nil {
return line, fmt.Errorf("Failed to read line")
}
if err := binary.Read(r, binary.LittleEndian, &line.BrushColor); err != nil {
return line, fmt.Errorf("Failed to read line")
}
if err := binary.Read(r, binary.LittleEndian, &line.Padding); err != nil {
return line, fmt.Errorf("Failed to read line")
}
if err := binary.Read(r, binary.LittleEndian, &line.BrushSize); err != nil {
return line, fmt.Errorf("Failed to read line")
}
// this new attribute has been added in v5
if r.version == V5 {
if err := binary.Read(r, binary.LittleEndian, &line.Unknown); err != nil {
return line, fmt.Errorf("Failed to read line")
}
}
nbPoints, err := r.readNumber()
if err != nil {
return line, err
}
if nbPoints == 0 {
return line, nil
}
line.Points = make([]Point, nbPoints)
for i := uint32(0); i < nbPoints; i++ {
p, err := r.readPoint()
if err != nil {
return line, err
}
line.Points[i] = p
}
return line, nil
}
func (r *reader) readPoint() (Point, error) {
var point Point
if err := binary.Read(r, binary.LittleEndian, &point.X); err != nil {
return point, fmt.Errorf("Failed to read point")
}
if err := binary.Read(r, binary.LittleEndian, &point.Y); err != nil {
return point, fmt.Errorf("Failed to read point")
}
if err := binary.Read(r, binary.LittleEndian, &point.Speed); err != nil {
return point, fmt.Errorf("Failed to read point")
}
if err := binary.Read(r, binary.LittleEndian, &point.Direction); err != nil {
return point, fmt.Errorf("Failed to read point")
}
if err := binary.Read(r, binary.LittleEndian, &point.Width); err != nil {
return point, fmt.Errorf("Failed to read point")
}
if err := binary.Read(r, binary.LittleEndian, &point.Pressure); err != nil {
return point, fmt.Errorf("Failed to read point")
}
return point, nil
}