Skip to content

Commit 2826499

Browse files
committed
Add first implementations and tests of data functions
1 parent 7a3d3d8 commit 2826499

34 files changed

+3757
-0
lines changed

.travis.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
dist: trusty
2+
sudo: required
3+
language: go
4+
5+
go:
6+
- tip
7+
- "1.10.3"
8+
9+
install: make deps
10+
script: make test
11+
12+
matrix:
13+
allow_failures:
14+
- go: tip
15+
fast_finish: true

Gopkg.lock

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Gopkg.toml example
2+
#
3+
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
4+
# for detailed Gopkg.toml documentation.
5+
#
6+
# required = ["github.com/user/thing/cmd/thing"]
7+
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8+
#
9+
# [[constraint]]
10+
# name = "github.com/user/project"
11+
# version = "1.0.0"
12+
#
13+
# [[constraint]]
14+
# name = "github.com/user/project2"
15+
# branch = "dev"
16+
# source = "github.com/myfork/project2"
17+
#
18+
# [[override]]
19+
# name = "github.com/x/y"
20+
# version = "2.4.0"
21+
#
22+
# [prune]
23+
# non-go = false
24+
# go-tests = true
25+
# unused-packages = true
26+
27+
28+
[[constraint]]
29+
branch = "v1"
30+
name = "gopkg.in/check.v1"
31+
32+
[prune]
33+
go-tests = true
34+
unused-packages = true

append.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package gotrax
2+
3+
import "math/big"
4+
5+
// AppendShort will append the serialization of the given value to the byte array
6+
// Data will be serialized big-endian
7+
func AppendShort(l []byte, r uint16) []byte {
8+
return append(l, SerializeShort(r)...)
9+
}
10+
11+
// AppendWord will append the serialization of the given value to the byte array
12+
// Data will be serialized big-endian
13+
func AppendWord(l []byte, r uint32) []byte {
14+
return append(l, SerializeWord(r)...)
15+
}
16+
17+
// AppendLong will append the serialization of the given value to the byte array
18+
// Data will be serialized big-endian
19+
func AppendLong(l []byte, r uint64) []byte {
20+
return append(l, SerializeLong(r)...)
21+
}
22+
23+
// AppendData will append the serialization of the given value to the byte array
24+
// Data will be serialized big-endian
25+
func AppendData(l, r []byte) []byte {
26+
return append(AppendWord(l, uint32(len(r))), r...)
27+
}
28+
29+
// AppendMPI will append the serialization of the given value to the byte array
30+
// Data will be serialized big-endian
31+
func AppendMPI(l []byte, r *big.Int) []byte {
32+
return AppendData(l, r.Bytes())
33+
}
34+
35+
// AppendMPIs will append the serialization of the given values to the byte array
36+
// Data will be serialized big-endian
37+
func AppendMPIs(l []byte, r ...*big.Int) []byte {
38+
for _, mpi := range r {
39+
l = AppendMPI(l, mpi)
40+
}
41+
return l
42+
}

append_test.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package gotrax
2+
3+
import (
4+
"math/big"
5+
"testing"
6+
"time"
7+
8+
. "gopkg.in/check.v1"
9+
)
10+
11+
func Test(t *testing.T) { TestingT(t) }
12+
13+
type GotraxSuite struct{}
14+
15+
var _ = Suite(&GotraxSuite{})
16+
17+
func (s *GotraxSuite) Test_AppendLong_serializesTimeCorrectly(c *C) {
18+
tt := time.Date(2028, 11, 5, 13, 46, 00, 13, time.UTC)
19+
num := tt.Unix()
20+
c.Assert(num, Equals, int64(0x6EB04118))
21+
c.Assert(AppendLong(nil, uint64(num)), DeepEquals, []byte{0x00, 0x00, 0x00, 0x00, 0x6e, 0xb0, 0x41, 0x18})
22+
23+
tt2 := time.Date(1968, 11, 5, 13, 46, 00, 13, time.UTC)
24+
num2 := tt2.Unix()
25+
c.Assert(num2, Equals, int64(-0x022B9768))
26+
c.Assert(AppendLong(nil, uint64(num2)), DeepEquals, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xD4, 0x68, 0x98})
27+
}
28+
29+
func (s *GotraxSuite) Test_AppendShort_willAppendTheShort(c *C) {
30+
before := []byte{0x12, 0x14}
31+
result := AppendShort(before, 0x4215)
32+
c.Assert(result, DeepEquals, []byte{0x12, 0x14, 0x42, 0x15})
33+
}
34+
35+
func (s *GotraxSuite) Test_AppendWord_WillAppendTheWord(c *C) {
36+
before := []byte{0x12, 0x14}
37+
result := AppendWord(before, 0x334D1215)
38+
c.Assert(result, DeepEquals, []byte{0x12, 0x14, 0x33, 0x4D, 0x12, 0x15})
39+
}
40+
41+
func (s *GotraxSuite) Test_AppendData_WillAppendBytes(c *C) {
42+
before := []byte{0x13, 0x54}
43+
result := AppendData(before, []byte{0x55, 0x12, 0x04, 0x8A, 0x00})
44+
c.Assert(result, DeepEquals, []byte{0x13, 0x54, 0x00, 0x00, 0x00, 0x05, 0x55, 0x12, 0x04, 0x8A, 0x00})
45+
}
46+
47+
func (s *GotraxSuite) Test_AppendMPI_WillAppendTheMPI(c *C) {
48+
before := []byte{0x13, 0x54}
49+
result := AppendMPI(before, new(big.Int).SetBytes([]byte{0x55, 0x12, 0x04, 0x8A, 0x00}))
50+
c.Assert(result, DeepEquals, []byte{0x13, 0x54, 0x00, 0x00, 0x00, 0x05, 0x55, 0x12, 0x04, 0x8A, 0x00})
51+
}
52+
53+
func (s *GotraxSuite) Test_AppendMPIs_WillAppendTheMPIs(c *C) {
54+
before := []byte{0x13, 0x54}
55+
one := new(big.Int).SetBytes([]byte{0x55, 0x12, 0x04, 0x8A, 0x00})
56+
two := new(big.Int).SetBytes([]byte{0x01, 0x53, 0xCC})
57+
three := new(big.Int).SetBytes([]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01})
58+
result := AppendMPIs(before, one, two, three)
59+
c.Assert(result, DeepEquals, []byte{0x13, 0x54, 0x00, 0x00, 0x00, 0x05, 0x55, 0x12, 0x04, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x53, 0xCC, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01})
60+
}

extract.go

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package gotrax
2+
3+
import (
4+
"math/big"
5+
"time"
6+
)
7+
8+
// ExtractByte will return the first byte, the rest, and a boolean indicating success
9+
// Data is expected to be in big-endian format
10+
func ExtractByte(d []byte) ([]byte, uint8, bool) {
11+
if len(d) < 1 {
12+
return nil, 0, false
13+
}
14+
15+
return d[1:], uint8(d[0]), true
16+
}
17+
18+
// ExtractShort will return the first short, the rest, and a boolean indicating success
19+
// Data is expected to be in big-endian format
20+
func ExtractShort(d []byte) ([]byte, uint16, bool) {
21+
if len(d) < 2 {
22+
return nil, 0, false
23+
}
24+
25+
return d[2:], DeserializeShort(d), true
26+
}
27+
28+
// ExtractWord will return the first word, the rest, and a boolean indicating success
29+
// Data is expected to be in big-endian format
30+
func ExtractWord(d []byte) ([]byte, uint32, bool) {
31+
if len(d) < 4 {
32+
return nil, 0, false
33+
}
34+
35+
return d[4:], DeserializeWord(d), true
36+
}
37+
38+
// ExtractLong will return the first long, the rest, and a boolean indicating success
39+
// Data is expected to be in big-endian format
40+
func ExtractLong(d []byte) ([]byte, uint64, bool) {
41+
if len(d) < 8 {
42+
return nil, 0, false
43+
}
44+
45+
return d[8:], DeserializeLong(d), true
46+
}
47+
48+
// ExtractData will return the first data, the rest, and a boolean indicating success
49+
// A Data is serialized as a word indicating length, and then as many bytes as that length
50+
// Data is expected to be in big-endian format
51+
func ExtractData(d []byte) (newPoint []byte, data []byte, ok bool) {
52+
newPoint, length, ok := ExtractWord(d)
53+
if !ok || len(newPoint) < int(length) {
54+
return nil, nil, false
55+
}
56+
57+
data = newPoint[:int(length)]
58+
newPoint = newPoint[int(length):]
59+
ok = true
60+
return
61+
}
62+
63+
// ExtractTime will return the first time, the rest, and a boolean indicating success
64+
// Time is encoded as a big-endian 64bit number
65+
func ExtractTime(d []byte) (newPoint []byte, t time.Time, ok bool) {
66+
newPoint, tt, ok := ExtractLong(d)
67+
if !ok {
68+
return nil, time.Time{}, false
69+
}
70+
t = time.Unix(int64(tt), 0).In(time.UTC)
71+
ok = true
72+
return
73+
}
74+
75+
// ExtractFixedData will return the first l bytes, the rest, and a boolean indicating success
76+
func ExtractFixedData(d []byte, l int) (newPoint []byte, data []byte, ok bool) {
77+
if len(d) < l {
78+
return nil, nil, false
79+
}
80+
return d[l:], d[0:l], true
81+
}
82+
83+
// ExtractMPI will return the first MPI, the rest, and a boolean indicating success
84+
// The MPI is encoded as a word length, followed by length bytes indicating the minimal representation of the MPI in the obvious format.
85+
// Data is expected to be in big-endian format
86+
func ExtractMPI(d []byte) (newPoint []byte, mpi *big.Int, ok bool) {
87+
d, mpiLen, ok := ExtractWord(d)
88+
if !ok || len(d) < int(mpiLen) {
89+
return nil, nil, false
90+
}
91+
92+
mpi = new(big.Int).SetBytes(d[:int(mpiLen)])
93+
newPoint = d[int(mpiLen):]
94+
ok = true
95+
return
96+
}
97+
98+
// ExtractMPIs will return the first len MPIs, the rest, and a boolean indicating success
99+
// The length is indicated by a word, followed by length MPIs
100+
// Data is expected to be in big-endian format
101+
func ExtractMPIs(d []byte) ([]byte, []*big.Int, bool) {
102+
current, mpiCount, ok := ExtractWord(d)
103+
if !ok {
104+
return nil, nil, false
105+
}
106+
result := make([]*big.Int, int(mpiCount))
107+
for i := 0; i < int(mpiCount); i++ {
108+
current, result[i], ok = ExtractMPI(current)
109+
if !ok {
110+
return nil, nil, false
111+
}
112+
}
113+
return current, result, true
114+
}

0 commit comments

Comments
 (0)