forked from mlnoga/rct
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbuild.go
59 lines (51 loc) · 1.54 KB
/
build.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
package rct
import (
"bytes"
)
// Builds RCT datagrams into an internal buffer, with escaping and CRC correction
type DatagramBuilder struct {
buffer bytes.Buffer
crc CRC
}
// Resets the internal buffer and CRC
func (rdb *DatagramBuilder) Reset() {
rdb.buffer.Reset()
rdb.crc.Reset()
}
// Adds a byte to the internal buffer, handling escaping and CRC calculation
func (rdb *DatagramBuilder) WriteByte(b byte) {
if (b == 0x2b) || (b == 0x2d) {
rdb.buffer.WriteByte(0x2d) // escape in byte stream (not in CRC stream)
}
rdb.buffer.WriteByte(b)
rdb.crc.Update(b)
}
// Adds a byte to the internal buffer, without escaping or CRC calculation
func (rdb *DatagramBuilder) WriteByteUnescapedNoCRC(b byte) {
rdb.buffer.WriteByte(b)
}
// Writes the CRC into the current datastream, handling CRC calcuation padding to an even number of bytes
func (rdb *DatagramBuilder) WriteCRC() {
crc := rdb.crc.Get()
rdb.buffer.WriteByte(byte(crc >> 8))
rdb.buffer.WriteByte(byte(crc & 0xff))
}
// Builds a complete datagram into the buffer
func (rdb *DatagramBuilder) Build(dg *Datagram) {
rdb.Reset()
rdb.WriteByteUnescapedNoCRC(0x2b) // Start byte
rdb.WriteByte(byte(dg.Cmd))
rdb.WriteByte(byte(len(dg.Data) + 4))
rdb.WriteByte(byte(dg.Id >> 24))
rdb.WriteByte(byte((dg.Id >> 16) & 0xff))
rdb.WriteByte(byte((dg.Id >> 8) & 0xff))
rdb.WriteByte(byte(dg.Id & 0xff))
for _, d := range dg.Data {
rdb.WriteByte(d)
}
rdb.WriteCRC()
}
// Returns the datagram built so far as an array of bytes
func (r *DatagramBuilder) Bytes() []byte {
return r.buffer.Bytes()
}