mirror of
https://github.com/jwetzell/psn-go.git
synced 2026-08-24 00:19:24 +00:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e0d4b58606 | |||
| 2df4cd56f7 | |||
| 145c13a976 | |||
| e7bdeb46ff | |||
| a79bca637c | |||
| eb8c6aba19 | |||
| 0b20f3ffb9 | |||
| 98a458ca43 | |||
| e3a7268487 | |||
| 77c0be5b35 | |||
| 7b1dc4bfd6 | |||
| 7dd6d45a08 | |||
| 631537b473 | |||
| bdaf7fd327 | |||
| d53fe09bfc | |||
| a0ba854fee | |||
| 4c508c37f3 | |||
| c7f503ee99 | |||
| 75ba023226 | |||
| b1e1367662 | |||
| 3271c0f82c | |||
| 15cf2e8052 | |||
| f7ceefc203 | |||
| 3af4413e84 | |||
| 017f8ea20f |
@@ -7,8 +7,6 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'main'
|
- 'main'
|
||||||
paths:
|
|
||||||
- 'internal/decoders/**'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test_decoders:
|
test_decoders:
|
||||||
@@ -21,7 +19,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ^1.23
|
go-version-file: "./go.mod"
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: go test -cover -coverprofile=decoders_coverage.txt ./internal/decoders/...
|
run: go test -cover -coverprofile=decoders_coverage.txt ./internal/decoders/...
|
||||||
@@ -30,19 +28,4 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: decoders-code-coverage
|
name: decoders-code-coverage
|
||||||
path: decoders_coverage.txt # Make sure to use the same file name you chose for the "-coverprofile" in the "Test" step
|
path: decoders_coverage.txt
|
||||||
|
|
||||||
code_coverage:
|
|
||||||
name: "Code coverage report"
|
|
||||||
if: github.event_name == 'pull_request' # Do not run when workflow is triggered by push to main branch
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: test_decoders
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
|
||||||
- uses: fgrosse/go-coverage-report@v1.1.1 # Consider using a Git revision for maximum security
|
|
||||||
with:
|
|
||||||
coverage-artifact-name: "decoders-code-coverage" # can be omitted if you used this default value
|
|
||||||
coverage-file-name: "decoders_coverage.txt" # can be omitted if you used this default value
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
name: "Test Encoders"
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, reopened, synchronize]
|
||||||
|
paths:
|
||||||
|
- 'internal/encoders/**'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test_encoders:
|
||||||
|
name: "test encoders"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version-file: "./go.mod"
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: go test -cover -coverprofile=encoders_coverage.txt ./internal/encoders/...
|
||||||
|
|
||||||
|
- name: Archive code coverage results
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: encoders-code-coverage
|
||||||
|
path: encoders_coverage.txt
|
||||||
+14
-14
@@ -1,27 +1,26 @@
|
|||||||
package psn
|
package psn
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
"github.com/jwetzell/psn-go/internal/decoders"
|
"github.com/jwetzell/psn-go/internal/decoders"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
lastInfoPacketHeader *decoders.PacketHeaderChunk
|
infoPacketFrames map[uint8][]chunks.InfoPacketChunk
|
||||||
lastDataPacketHeader *decoders.PacketHeaderChunk
|
dataPacketFrames map[uint8][]chunks.DataPacketChunk
|
||||||
infoPacketFrames map[uint8][]decoders.InfoPacketChunk
|
Trackers map[uint16]*Tracker
|
||||||
dataPacketFrames map[uint8][]decoders.DataPacketChunk
|
SystemName string
|
||||||
Trackers map[uint16]*Tracker
|
|
||||||
SystemName string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDecoder() *Decoder {
|
func NewDecoder() *Decoder {
|
||||||
var decoder Decoder
|
var decoder Decoder
|
||||||
decoder.infoPacketFrames = map[uint8][]decoders.InfoPacketChunk{}
|
decoder.infoPacketFrames = map[uint8][]chunks.InfoPacketChunk{}
|
||||||
decoder.dataPacketFrames = map[uint8][]decoders.DataPacketChunk{}
|
decoder.dataPacketFrames = map[uint8][]chunks.DataPacketChunk{}
|
||||||
decoder.Trackers = map[uint16]*Tracker{}
|
decoder.Trackers = map[uint16]*Tracker{}
|
||||||
return &decoder
|
return &decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) updateInfo(framePackets []decoders.InfoPacketChunk) {
|
func (d *Decoder) updateInfo(framePackets []chunks.InfoPacketChunk) {
|
||||||
for _, framePacket := range framePackets {
|
for _, framePacket := range framePackets {
|
||||||
d.SystemName = framePacket.Data.SystemName.Data.SystemName
|
d.SystemName = framePacket.Data.SystemName.Data.SystemName
|
||||||
for _, infoTrackerChunk := range framePacket.Data.TrackerList.Data.Trackers {
|
for _, infoTrackerChunk := range framePacket.Data.TrackerList.Data.Trackers {
|
||||||
@@ -36,7 +35,7 @@ func (d *Decoder) updateInfo(framePackets []decoders.InfoPacketChunk) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) updateData(framePackets []decoders.DataPacketChunk) {
|
func (d *Decoder) updateData(framePackets []chunks.DataPacketChunk) {
|
||||||
for _, framePacket := range framePackets {
|
for _, framePacket := range framePackets {
|
||||||
for _, dataTrackerChunk := range framePacket.Data.TrackerList.Data.Trackers {
|
for _, dataTrackerChunk := range framePacket.Data.TrackerList.Data.Trackers {
|
||||||
tracker, ok := d.Trackers[dataTrackerChunk.Chunk.Header.Id]
|
tracker, ok := d.Trackers[dataTrackerChunk.Chunk.Header.Id]
|
||||||
@@ -57,7 +56,8 @@ func (d *Decoder) Decode(bytes []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if chunk.Header.Id == 0x6756 {
|
switch chunk.Header.Id {
|
||||||
|
case 0x6756:
|
||||||
infoPacket, err := decoders.DecodeInfoPacketChunk(bytes)
|
infoPacket, err := decoders.DecodeInfoPacketChunk(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -67,7 +67,7 @@ func (d *Decoder) Decode(bytes []byte) error {
|
|||||||
_, ok := d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId]
|
_, ok := d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId] = []decoders.InfoPacketChunk{}
|
d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId] = []chunks.InfoPacketChunk{}
|
||||||
}
|
}
|
||||||
d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId] = append(d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId], infoPacket)
|
d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId] = append(d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId], infoPacket)
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ func (d *Decoder) Decode(bytes []byte) error {
|
|||||||
d.updateInfo(d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId])
|
d.updateInfo(d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId])
|
||||||
delete(d.infoPacketFrames, currentInfoPacketHeader.Data.FrameId)
|
delete(d.infoPacketFrames, currentInfoPacketHeader.Data.FrameId)
|
||||||
}
|
}
|
||||||
} else if chunk.Header.Id == 0x6755 {
|
case 0x6755:
|
||||||
dataPacket, err := decoders.DecodeDataPacketChunk(bytes)
|
dataPacket, err := decoders.DecodeDataPacketChunk(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -85,7 +85,7 @@ func (d *Decoder) Decode(bytes []byte) error {
|
|||||||
_, ok := d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId]
|
_, ok := d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId] = []decoders.DataPacketChunk{}
|
d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId] = []chunks.DataPacketChunk{}
|
||||||
}
|
}
|
||||||
d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId] = append(d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId], dataPacket)
|
d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId] = append(d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId], dataPacket)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -18,7 +18,7 @@ func (e *Encoder) ResetInfoFrameId() {
|
|||||||
e.infoFrameId = 1
|
e.infoFrameId = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) GetInfoPackets(timestamp uint64, trackers []Tracker) [][]byte {
|
func (e *Encoder) GetInfoPackets(timestamp uint64, trackers []*Tracker) [][]byte {
|
||||||
systemNameChunk := encoders.EncodeInfoSystemNameChunk(e.SystemName)
|
systemNameChunk := encoders.EncodeInfoSystemNameChunk(e.SystemName)
|
||||||
|
|
||||||
trackerChunks := [][]byte{}
|
trackerChunks := [][]byte{}
|
||||||
@@ -58,7 +58,7 @@ func (e *Encoder) GetInfoPackets(timestamp uint64, trackers []Tracker) [][]byte
|
|||||||
return infoPackets
|
return infoPackets
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) GetDataPackets(timestamp uint64, trackers []Tracker) [][]byte {
|
func (e *Encoder) GetDataPackets(timestamp uint64, trackers []*Tracker) [][]byte {
|
||||||
trackerChunks := [][]byte{}
|
trackerChunks := [][]byte{}
|
||||||
|
|
||||||
for _, tracker := range trackers {
|
for _, tracker := range trackers {
|
||||||
|
|||||||
+16
-10
@@ -7,11 +7,11 @@ import (
|
|||||||
"github.com/jwetzell/psn-go"
|
"github.com/jwetzell/psn-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getNTrackers(n int) []psn.Tracker {
|
func getNTrackers(n int) []*psn.Tracker {
|
||||||
trackers := []psn.Tracker{}
|
trackers := []*psn.Tracker{}
|
||||||
|
|
||||||
for index := 0; index < n; index++ {
|
for index := range n {
|
||||||
tracker := psn.Tracker{Id: uint16(index), Name: "Tracker"}
|
tracker := &psn.Tracker{Id: uint16(index), Name: "Tracker"}
|
||||||
tracker.SetPos(0, 0, 0)
|
tracker.SetPos(0, 0, 0)
|
||||||
tracker.SetSpeed(0, 0, 0)
|
tracker.SetSpeed(0, 0, 0)
|
||||||
tracker.SetOri(0, 0, 0)
|
tracker.SetOri(0, 0, 0)
|
||||||
@@ -61,31 +61,37 @@ func benchmark(trackerCount int, iterations int, encoder psn.Encoder, decoder ps
|
|||||||
|
|
||||||
latestEncodedPackets := [][]byte{}
|
latestEncodedPackets := [][]byte{}
|
||||||
|
|
||||||
for index := 0; index < iterations; index++ {
|
for range iterations {
|
||||||
latestEncodedPackets = encoder.GetDataPackets(uint64(timestamp), trackers)
|
latestEncodedPackets = encoder.GetDataPackets(uint64(timestamp), trackers)
|
||||||
}
|
}
|
||||||
benchmarkResults.data.encode = float64(time.Now().UnixMicro()-dataEncoderStart) / 1000.0
|
benchmarkResults.data.encode = float64(time.Now().UnixMicro()-dataEncoderStart) / 1000.0
|
||||||
|
|
||||||
_ = latestEncodedPackets
|
_ = latestEncodedPackets
|
||||||
dataDecodedStart := time.Now().UnixMicro()
|
dataDecodedStart := time.Now().UnixMicro()
|
||||||
for index := 0; index < iterations; index++ {
|
for range iterations {
|
||||||
for _, packet := range latestEncodedPackets {
|
for _, packet := range latestEncodedPackets {
|
||||||
decoder.Decode(packet)
|
err := decoder.Decode(packet)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to decode packet, error: %v\n", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
benchmarkResults.data.decode = float64(time.Now().UnixMicro()-dataDecodedStart) / 1000.0
|
benchmarkResults.data.decode = float64(time.Now().UnixMicro()-dataDecodedStart) / 1000.0
|
||||||
|
|
||||||
// INFO
|
// INFO
|
||||||
infoEncoderStart := time.Now().UnixMicro()
|
infoEncoderStart := time.Now().UnixMicro()
|
||||||
for index := 0; index < iterations; index++ {
|
for range iterations {
|
||||||
latestEncodedPackets = encoder.GetInfoPackets(uint64(timestamp), trackers)
|
latestEncodedPackets = encoder.GetInfoPackets(uint64(timestamp), trackers)
|
||||||
}
|
}
|
||||||
benchmarkResults.info.encode = float64(time.Now().UnixMicro()-infoEncoderStart) / 1000.0
|
benchmarkResults.info.encode = float64(time.Now().UnixMicro()-infoEncoderStart) / 1000.0
|
||||||
|
|
||||||
infoDecodeStart := time.Now().UnixMicro()
|
infoDecodeStart := time.Now().UnixMicro()
|
||||||
for index := 0; index < iterations; index++ {
|
for range iterations {
|
||||||
for _, packet := range latestEncodedPackets {
|
for _, packet := range latestEncodedPackets {
|
||||||
decoder.Decode(packet)
|
err := decoder.Decode(packet)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to decode packet, error: %v\n", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
benchmarkResults.info.decode = float64(time.Now().UnixMicro()-infoDecodeStart) / 1000.0
|
benchmarkResults.info.decode = float64(time.Now().UnixMicro()-infoDecodeStart) / 1000.0
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ func main() {
|
|||||||
VersionLow: 3,
|
VersionLow: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
tracker := psn.Tracker{
|
tracker := &psn.Tracker{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
Name: "Tracker 1",
|
Name: "Tracker 1",
|
||||||
}
|
}
|
||||||
|
|
||||||
tracker.SetPos(1.0, 1.0, 1.0)
|
tracker.SetPos(1.0, 1.0, 1.0)
|
||||||
|
|
||||||
trackers := []psn.Tracker{
|
trackers := []*psn.Tracker{
|
||||||
tracker,
|
tracker,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+44
-36
@@ -23,62 +23,70 @@ func main() {
|
|||||||
VersionLow: 0,
|
VersionLow: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
trackers := []psn.Tracker{}
|
trackers := []*psn.Tracker{}
|
||||||
|
|
||||||
trackers = append(trackers, psn.Tracker{Id: 0, Name: "Sun"})
|
trackers = append(trackers, &psn.Tracker{Id: 0, Name: "Sun"})
|
||||||
trackers = append(trackers, psn.Tracker{Id: 1, Name: "Mercury"})
|
trackers = append(trackers, &psn.Tracker{Id: 1, Name: "Mercury"})
|
||||||
trackers = append(trackers, psn.Tracker{Id: 2, Name: "Venus"})
|
trackers = append(trackers, &psn.Tracker{Id: 2, Name: "Venus"})
|
||||||
trackers = append(trackers, psn.Tracker{Id: 3, Name: "Earth"})
|
trackers = append(trackers, &psn.Tracker{Id: 3, Name: "Earth"})
|
||||||
trackers = append(trackers, psn.Tracker{Id: 4, Name: "Mars"})
|
trackers = append(trackers, &psn.Tracker{Id: 4, Name: "Mars"})
|
||||||
trackers = append(trackers, psn.Tracker{Id: 5, Name: "Jupiter"})
|
trackers = append(trackers, &psn.Tracker{Id: 5, Name: "Jupiter"})
|
||||||
trackers = append(trackers, psn.Tracker{Id: 6, Name: "Saturn"})
|
trackers = append(trackers, &psn.Tracker{Id: 6, Name: "Saturn"})
|
||||||
trackers = append(trackers, psn.Tracker{Id: 7, Name: "Uranus"})
|
trackers = append(trackers, &psn.Tracker{Id: 7, Name: "Uranus"})
|
||||||
trackers = append(trackers, psn.Tracker{Id: 8, Name: "Neptune"})
|
trackers = append(trackers, &psn.Tracker{Id: 8, Name: "Neptune"})
|
||||||
trackers = append(trackers, psn.Tracker{Id: 9, Name: "Pluto"})
|
trackers = append(trackers, &psn.Tracker{Id: 9, Name: "Pluto"})
|
||||||
|
|
||||||
orbits := []float32{1.0, 88.0, 224.7, 365.2, 687, 4332, 10760, 30700, 60200, 90600}
|
orbits := []float32{1.0, 88.0, 224.7, 365.2, 687, 4332, 10760, 30700, 60200, 90600}
|
||||||
distFromSun := []float32{0, 0.58, 1.08, 1.5, 2.28, 7.78, 14.29, 28.71, 45.04, 59.13}
|
distFromSun := []float32{0, 0.58, 1.08, 1.5, 2.28, 7.78, 14.29, 28.71, 45.04, 59.13}
|
||||||
|
|
||||||
timestamp := 0
|
timestamp := 0
|
||||||
|
|
||||||
lastInfoMillis := time.Now().UnixMilli()
|
dataTicker := time.NewTicker(time.Millisecond * 16)
|
||||||
lastDataMillis := time.Now().UnixMilli()
|
infoTicker := time.NewTicker(time.Millisecond * 1000)
|
||||||
|
|
||||||
for {
|
go func() {
|
||||||
if (time.Now().UnixMilli() - lastInfoMillis) > 500 {
|
for {
|
||||||
slog.Info("Sending Info Packets")
|
for index, tracker := range trackers {
|
||||||
infoPackets := encoder.GetInfoPackets(uint64(timestamp), trackers)
|
orbit := orbits[index]
|
||||||
for _, infoPacket := range infoPackets {
|
|
||||||
client.Write(infoPacket)
|
|
||||||
}
|
|
||||||
lastInfoMillis = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time.Now().UnixMilli() - lastDataMillis) > 5 {
|
|
||||||
for index, orbit := range orbits {
|
|
||||||
a := 1.0 / orbit
|
a := 1.0 / orbit
|
||||||
b := distFromSun[index]
|
b := distFromSun[index]
|
||||||
x := timestamp
|
x := timestamp
|
||||||
cb := math.Cos(float64(a*float32(x))) * float64(b)
|
cb := math.Cos(float64(a*float32(x))) * float64(b)
|
||||||
sb := math.Sin(float64(a*float32(x))) * float64(b)
|
sb := math.Sin(float64(a*float32(x))) * float64(b)
|
||||||
|
|
||||||
trackers[index].SetPos(float32(sb), 0, float32(cb))
|
tracker.SetPos(float32(sb), 0, float32(cb))
|
||||||
trackers[index].SetSpeed(a*float32(cb), 0, -a*float32(sb))
|
tracker.SetSpeed(a*float32(cb), 0, -a*float32(sb))
|
||||||
trackers[index].SetOri(0, float32(x)/1000.0, 0)
|
tracker.SetOri(0, float32(x)/1000.0, 0)
|
||||||
trackers[index].SetAccel(-a*a*float32(sb), 0, -a*a*float32(cb))
|
tracker.SetAccel(-a*a*float32(sb), 0, -a*a*float32(cb))
|
||||||
trackers[index].SetTrgtPos(3, 14, 16)
|
tracker.SetTrgtPos(3, 14, 16)
|
||||||
trackers[index].SetStatus(float32(index) / 10.0)
|
tracker.SetStatus(float32(index) / 10.0)
|
||||||
trackers[index].SetTimestamp(uint64(timestamp))
|
tracker.SetTimestamp(uint64(timestamp))
|
||||||
}
|
}
|
||||||
|
time.Sleep(time.Millisecond * 16)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-infoTicker.C:
|
||||||
|
slog.Info("Sending Info Packets")
|
||||||
|
infoPackets := encoder.GetInfoPackets(uint64(timestamp), trackers)
|
||||||
|
for _, infoPacket := range infoPackets {
|
||||||
|
_, err := client.Write(infoPacket)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to send info packet", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-dataTicker.C:
|
||||||
slog.Info("Sending Data Packets")
|
slog.Info("Sending Data Packets")
|
||||||
dataPackets := encoder.GetDataPackets(uint64(timestamp), trackers)
|
dataPackets := encoder.GetDataPackets(uint64(timestamp), trackers)
|
||||||
for _, DataPacket := range dataPackets {
|
for _, dataPacket := range dataPackets {
|
||||||
client.Write(DataPacket)
|
_, err := client.Write(dataPacket)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to send data packet", "error", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lastDataMillis = time.Now().UnixMilli()
|
|
||||||
timestamp += 1
|
timestamp += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
module github.com/jwetzell/psn-go
|
module github.com/jwetzell/psn-go
|
||||||
|
|
||||||
go 1.23.1
|
go 1.25.3
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type ChunkHeader struct {
|
||||||
|
Id uint16
|
||||||
|
DataLen uint16
|
||||||
|
HasSubchunks bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Chunk struct {
|
||||||
|
ChunkData []byte
|
||||||
|
Header ChunkHeader
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type DataPacketChunkData struct {
|
||||||
|
PacketHeader *PacketHeaderChunk
|
||||||
|
TrackerList *DataTrackerListChunk
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataPacketChunk struct {
|
||||||
|
Data DataPacketChunkData
|
||||||
|
Chunk Chunk
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type DataTrackerChunkData struct {
|
||||||
|
Pos *DataTrackerXYZChunk
|
||||||
|
Speed *DataTrackerXYZChunk
|
||||||
|
Ori *DataTrackerXYZChunk
|
||||||
|
Status *DataTrackerStatusChunk
|
||||||
|
Accel *DataTrackerXYZChunk
|
||||||
|
TrgtPos *DataTrackerXYZChunk
|
||||||
|
Timestamp *DataTrackerTimestampChunk
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataTrackerChunk struct {
|
||||||
|
Data DataTrackerChunkData
|
||||||
|
Chunk Chunk
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type DataTrackerListChunkData struct {
|
||||||
|
Trackers []DataTrackerChunk
|
||||||
|
}
|
||||||
|
type DataTrackerListChunk struct {
|
||||||
|
Chunk Chunk
|
||||||
|
Data DataTrackerListChunkData
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type DataTrackerStatusChunkData struct {
|
||||||
|
Validity float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataTrackerStatusChunk struct {
|
||||||
|
Chunk Chunk
|
||||||
|
Data DataTrackerStatusChunkData
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type DataTrackerTimestampChunkData struct {
|
||||||
|
Timestamp uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataTrackerTimestampChunk struct {
|
||||||
|
Chunk Chunk
|
||||||
|
Data DataTrackerTimestampChunkData
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type DataTrackerXYZChunkData struct {
|
||||||
|
X float32
|
||||||
|
Y float32
|
||||||
|
Z float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataTrackerXYZChunk struct {
|
||||||
|
Chunk Chunk
|
||||||
|
Data DataTrackerXYZChunkData
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type InfoPacketChunkData struct {
|
||||||
|
PacketHeader *PacketHeaderChunk
|
||||||
|
SystemName *InfoSystemNameChunk
|
||||||
|
TrackerList *InfoTrackerListChunk
|
||||||
|
}
|
||||||
|
|
||||||
|
type InfoPacketChunk struct {
|
||||||
|
Data InfoPacketChunkData
|
||||||
|
Chunk Chunk
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type InfoSystemNameChunkData struct {
|
||||||
|
SystemName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type InfoSystemNameChunk struct {
|
||||||
|
Data InfoSystemNameChunkData
|
||||||
|
Chunk Chunk
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type InfoTrackerChunkData struct {
|
||||||
|
TrackerName *InfoTrackerNameChunk
|
||||||
|
}
|
||||||
|
|
||||||
|
type InfoTrackerChunk struct {
|
||||||
|
Data InfoTrackerChunkData
|
||||||
|
Chunk Chunk
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type InfoTrackerListChunkData struct {
|
||||||
|
Trackers []InfoTrackerChunk
|
||||||
|
}
|
||||||
|
|
||||||
|
type InfoTrackerListChunk struct {
|
||||||
|
Chunk Chunk
|
||||||
|
Data InfoTrackerListChunkData
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type InfoTrackerNameChunkData struct {
|
||||||
|
TrackerName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type InfoTrackerNameChunk struct {
|
||||||
|
Data InfoTrackerNameChunkData
|
||||||
|
Chunk Chunk
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package chunks
|
||||||
|
|
||||||
|
type PacketHeaderChunkData struct {
|
||||||
|
PacketTimestamp uint64
|
||||||
|
VersionHigh uint8
|
||||||
|
VersionLow uint8
|
||||||
|
FrameId uint8
|
||||||
|
FramePacketCount uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketHeaderChunk struct {
|
||||||
|
Chunk Chunk
|
||||||
|
Data PacketHeaderChunkData
|
||||||
|
}
|
||||||
+11
-16
@@ -3,23 +3,14 @@ package decoders
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChunkHeader struct {
|
func DecodeChunk(bytes []byte) (chunks.Chunk, error) {
|
||||||
Id uint16
|
|
||||||
DataLen uint16
|
|
||||||
HasSubchunks bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Chunk struct {
|
|
||||||
ChunkData []byte
|
|
||||||
Header ChunkHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeChunk(bytes []byte) (Chunk, error) {
|
|
||||||
|
|
||||||
if len(bytes) < 4 {
|
if len(bytes) < 4 {
|
||||||
return Chunk{}, errors.New("chunk must be at least 4 bytes")
|
return chunks.Chunk{}, errors.New("chunk must be at least 4 bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
id := binary.LittleEndian.Uint16(bytes[0:2])
|
id := binary.LittleEndian.Uint16(bytes[0:2])
|
||||||
@@ -27,21 +18,25 @@ func DecodeChunk(bytes []byte) (Chunk, error) {
|
|||||||
|
|
||||||
data_len := lengthAndFlag
|
data_len := lengthAndFlag
|
||||||
|
|
||||||
has_subchunks := lengthAndFlag > 32768
|
has_subchunks := lengthAndFlag >= 32768
|
||||||
|
|
||||||
if has_subchunks {
|
if has_subchunks {
|
||||||
data_len = data_len - 32768
|
data_len = data_len - 32768
|
||||||
}
|
}
|
||||||
|
|
||||||
header := ChunkHeader{
|
header := chunks.ChunkHeader{
|
||||||
Id: id,
|
Id: id,
|
||||||
DataLen: data_len,
|
DataLen: data_len,
|
||||||
HasSubchunks: has_subchunks,
|
HasSubchunks: has_subchunks,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(bytes) < 4+int(header.DataLen) {
|
||||||
|
return chunks.Chunk{}, errors.New("chunk data length is greater than the number of bytes")
|
||||||
|
}
|
||||||
|
|
||||||
chunk_data := bytes[4 : 4+header.DataLen]
|
chunk_data := bytes[4 : 4+header.DataLen]
|
||||||
|
|
||||||
return Chunk{
|
return chunks.Chunk{
|
||||||
Header: header,
|
Header: header,
|
||||||
ChunkData: chunk_data,
|
ChunkData: chunk_data,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
package decoders
|
package decoders
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGoodChunkDecoding(t *testing.T) {
|
func TestGoodChunkDecoding(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
description string
|
description string
|
||||||
bytes []byte
|
bytes []byte
|
||||||
expected Chunk
|
expected chunks.Chunk
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
description: "info packet",
|
description: "info packet",
|
||||||
@@ -20,8 +21,8 @@ func TestGoodChunkDecoding(t *testing.T) {
|
|||||||
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
||||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
||||||
},
|
},
|
||||||
expected: Chunk{
|
expected: chunks.Chunk{
|
||||||
Header: ChunkHeader{
|
Header: chunks.ChunkHeader{
|
||||||
Id: uint16(26454),
|
Id: uint16(26454),
|
||||||
DataLen: uint16(52),
|
DataLen: uint16(52),
|
||||||
HasSubchunks: true,
|
HasSubchunks: true,
|
||||||
@@ -40,8 +41,8 @@ func TestGoodChunkDecoding(t *testing.T) {
|
|||||||
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
||||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||||
},
|
},
|
||||||
expected: Chunk{
|
expected: chunks.Chunk{
|
||||||
Header: ChunkHeader{
|
Header: chunks.ChunkHeader{
|
||||||
Id: uint16(26453),
|
Id: uint16(26453),
|
||||||
DataLen: uint16(40),
|
DataLen: uint16(40),
|
||||||
HasSubchunks: true,
|
HasSubchunks: true,
|
||||||
@@ -56,19 +57,17 @@ func TestGoodChunkDecoding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeChunk(testCase.bytes)
|
||||||
|
|
||||||
actual, err := DecodeChunk(testCase.bytes)
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
fmt.Println(err)
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
|
||||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
|
||||||
fmt.Printf("expected: %v\n", testCase.expected)
|
|
||||||
fmt.Printf("actual: %v\n", actual)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,18 +85,53 @@ func TestBadChunkDecoding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
_, err := DecodeChunk(testCase.bytes)
|
||||||
|
|
||||||
_, err := DecodeChunk(testCase.bytes)
|
if err == nil {
|
||||||
|
t.Error("should have failed fail to decode chunk properly")
|
||||||
if err == nil {
|
}
|
||||||
t.Errorf("Test '%s' should have failed fail to decode chunk properly", testCase.description)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), testCase.errorShouldContain) {
|
|
||||||
t.Errorf("Test '%s' did not return the correct error", testCase.description)
|
|
||||||
fmt.Printf("expected: %v\n", testCase.errorShouldContain)
|
|
||||||
fmt.Printf("actual: %v\n", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if !strings.Contains(err.Error(), testCase.errorShouldContain) {
|
||||||
|
t.Errorf("did not return the correct error expected: %s, got: %s", testCase.errorShouldContain, err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkChunkDecoding(b *testing.B) {
|
||||||
|
data := []byte{
|
||||||
|
0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||||
|
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
||||||
|
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
||||||
|
}
|
||||||
|
for b.Loop() {
|
||||||
|
_, err := DecodeChunk(data)
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzChunkDecoding(f *testing.F) {
|
||||||
|
seedCases := [][]byte{
|
||||||
|
{
|
||||||
|
0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||||
|
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
||||||
|
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||||
|
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
||||||
|
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, seed := range seedCases {
|
||||||
|
f.Add(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Fuzz(func(t *testing.T, bytes []byte) {
|
||||||
|
_, _ = DecodeChunk(bytes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,26 +3,18 @@ package decoders
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DataPacketChunkData struct {
|
func DecodeDataPacketChunk(bytes []byte) (chunks.DataPacketChunk, error) {
|
||||||
PacketHeader *PacketHeaderChunk
|
|
||||||
TrackerList *DataTrackerListChunk
|
|
||||||
}
|
|
||||||
|
|
||||||
type DataPacketChunk struct {
|
|
||||||
Data DataPacketChunkData
|
|
||||||
Chunk Chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeDataPacketChunk(bytes []byte) (DataPacketChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataPacketChunk{}, err
|
return chunks.DataPacketChunk{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := DataPacketChunkData{}
|
data := chunks.DataPacketChunkData{}
|
||||||
|
|
||||||
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
||||||
offset := 0
|
offset := 0
|
||||||
@@ -32,7 +24,7 @@ func DecodeDataPacketChunk(bytes []byte) (DataPacketChunk, error) {
|
|||||||
case 0x0000:
|
case 0x0000:
|
||||||
packet_header, err := DecodePacketHeaderChunk(chunk.ChunkData[offset:])
|
packet_header, err := DecodePacketHeaderChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataPacketChunk{}, err
|
return chunks.DataPacketChunk{}, err
|
||||||
}
|
}
|
||||||
data.PacketHeader = &packet_header
|
data.PacketHeader = &packet_header
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -42,7 +34,7 @@ func DecodeDataPacketChunk(bytes []byte) (DataPacketChunk, error) {
|
|||||||
case 0x0001:
|
case 0x0001:
|
||||||
tracker_list, err := DecodeDataTrackerListChunk(chunk.ChunkData[offset:])
|
tracker_list, err := DecodeDataTrackerListChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataPacketChunk{}, err
|
return chunks.DataPacketChunk{}, err
|
||||||
}
|
}
|
||||||
data.TrackerList = &tracker_list
|
data.TrackerList = &tracker_list
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -56,7 +48,7 @@ func DecodeDataPacketChunk(bytes []byte) (DataPacketChunk, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataPacketChunk{
|
return chunks.DataPacketChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodDataPacketChunkDecoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.DataPacketChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "DataPacketChunk",
|
||||||
|
bytes: []byte{
|
||||||
|
85, 103, 124, 128, 0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 104, 128, 1, 0, 100, 128, 0, 0,
|
||||||
|
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12,
|
||||||
|
0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64,
|
||||||
|
0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
expected: chunks.DataPacketChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{
|
||||||
|
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 104, 128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0,
|
||||||
|
128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0,
|
||||||
|
128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0,
|
||||||
|
64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
Header: chunks.ChunkHeader{
|
||||||
|
DataLen: 124, Id: 26453, HasSubchunks: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Data: chunks.DataPacketChunkData{
|
||||||
|
PacketHeader: &chunks.PacketHeaderChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.PacketHeaderChunkData{
|
||||||
|
PacketTimestamp: 1234567890,
|
||||||
|
VersionHigh: 2,
|
||||||
|
VersionLow: 3,
|
||||||
|
FrameId: 1,
|
||||||
|
FramePacketCount: 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TrackerList: &chunks.DataTrackerListChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{
|
||||||
|
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0,
|
||||||
|
0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4,
|
||||||
|
0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||||
|
6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 104, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerListChunkData{
|
||||||
|
Trackers: []chunks.DataTrackerChunk{
|
||||||
|
chunks.DataTrackerChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{
|
||||||
|
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0,
|
||||||
|
0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0,
|
||||||
|
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64,
|
||||||
|
64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 100, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerChunkData{
|
||||||
|
Pos: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Speed: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 1, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Ori: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 2, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: &chunks.DataTrackerStatusChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 4, Id: 3, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerStatusChunkData{
|
||||||
|
Validity: 1.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Accel: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 4, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TrgtPos: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 5, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Timestamp: &chunks.DataTrackerTimestampChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 8, Id: 6, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerTimestampChunkData{
|
||||||
|
Timestamp: 1234567890,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeDataPacketChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,31 +3,18 @@ package decoders
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DataTrackerChunkData struct {
|
func DecodeDataTrackerChunk(bytes []byte) (chunks.DataTrackerChunk, error) {
|
||||||
Pos *DataTrackerXYZChunk
|
|
||||||
Speed *DataTrackerXYZChunk
|
|
||||||
Ori *DataTrackerXYZChunk
|
|
||||||
Status *DataTrackerStatusChunk
|
|
||||||
Accel *DataTrackerXYZChunk
|
|
||||||
TrgtPos *DataTrackerXYZChunk
|
|
||||||
Timestamp *DataTrackerTimestampChunk
|
|
||||||
}
|
|
||||||
|
|
||||||
type DataTrackerChunk struct {
|
|
||||||
Data DataTrackerChunkData
|
|
||||||
Chunk Chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeDataTrackerChunk(bytes []byte) (DataTrackerChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerChunk{}, err
|
return chunks.DataTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := DataTrackerChunkData{}
|
data := chunks.DataTrackerChunkData{}
|
||||||
|
|
||||||
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
||||||
offset := 0
|
offset := 0
|
||||||
@@ -37,7 +24,7 @@ func DecodeDataTrackerChunk(bytes []byte) (DataTrackerChunk, error) {
|
|||||||
case 0x0000:
|
case 0x0000:
|
||||||
pos, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
pos, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerChunk{}, err
|
return chunks.DataTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
data.Pos = &pos
|
data.Pos = &pos
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -47,7 +34,7 @@ func DecodeDataTrackerChunk(bytes []byte) (DataTrackerChunk, error) {
|
|||||||
case 0x0001:
|
case 0x0001:
|
||||||
speed, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
speed, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerChunk{}, err
|
return chunks.DataTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
data.Speed = &speed
|
data.Speed = &speed
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -57,7 +44,7 @@ func DecodeDataTrackerChunk(bytes []byte) (DataTrackerChunk, error) {
|
|||||||
case 0x0002:
|
case 0x0002:
|
||||||
ori, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
ori, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerChunk{}, err
|
return chunks.DataTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
data.Ori = &ori
|
data.Ori = &ori
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -67,7 +54,7 @@ func DecodeDataTrackerChunk(bytes []byte) (DataTrackerChunk, error) {
|
|||||||
case 0x0003:
|
case 0x0003:
|
||||||
status, err := DecodeDataTrackerStatusChunk(chunk.ChunkData[offset:])
|
status, err := DecodeDataTrackerStatusChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerChunk{}, err
|
return chunks.DataTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
data.Status = &status
|
data.Status = &status
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -77,7 +64,7 @@ func DecodeDataTrackerChunk(bytes []byte) (DataTrackerChunk, error) {
|
|||||||
case 0x0004:
|
case 0x0004:
|
||||||
accel, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
accel, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerChunk{}, err
|
return chunks.DataTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
data.Accel = &accel
|
data.Accel = &accel
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -87,7 +74,7 @@ func DecodeDataTrackerChunk(bytes []byte) (DataTrackerChunk, error) {
|
|||||||
case 0x0005:
|
case 0x0005:
|
||||||
trgtpos, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
trgtpos, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerChunk{}, err
|
return chunks.DataTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
data.TrgtPos = &trgtpos
|
data.TrgtPos = &trgtpos
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -97,7 +84,7 @@ func DecodeDataTrackerChunk(bytes []byte) (DataTrackerChunk, error) {
|
|||||||
case 0x0006:
|
case 0x0006:
|
||||||
timestamp, err := DecodeDataTrackerTimestampChunk(chunk.ChunkData[offset:])
|
timestamp, err := DecodeDataTrackerTimestampChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerChunk{}, err
|
return chunks.DataTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
data.Timestamp = ×tamp
|
data.Timestamp = ×tamp
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -111,7 +98,7 @@ func DecodeDataTrackerChunk(bytes []byte) (DataTrackerChunk, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataTrackerChunk{
|
return chunks.DataTrackerChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodDataTrackerChunkDecoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.DataTrackerChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "DataTracker",
|
||||||
|
bytes: []byte{
|
||||||
|
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12,
|
||||||
|
0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64,
|
||||||
|
0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
expected: chunks.DataTrackerChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{
|
||||||
|
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0,
|
||||||
|
0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0,
|
||||||
|
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64,
|
||||||
|
64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 100, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerChunkData{
|
||||||
|
Pos: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Speed: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 1, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Ori: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 2, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: &chunks.DataTrackerStatusChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 4, Id: 3, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerStatusChunkData{
|
||||||
|
Validity: 1.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Accel: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 4, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TrgtPos: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 5, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Timestamp: &chunks.DataTrackerTimestampChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 8, Id: 6, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerTimestampChunkData{
|
||||||
|
Timestamp: 1234567890,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeDataTrackerChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,27 +1,21 @@
|
|||||||
package decoders
|
package decoders
|
||||||
|
|
||||||
type DataTrackerListChunkData struct {
|
import "github.com/jwetzell/psn-go/internal/chunks"
|
||||||
Trackers []DataTrackerChunk
|
|
||||||
}
|
|
||||||
type DataTrackerListChunk struct {
|
|
||||||
Chunk Chunk
|
|
||||||
Data DataTrackerListChunkData
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeDataTrackerListChunk(bytes []byte) (DataTrackerListChunk, error) {
|
func DecodeDataTrackerListChunk(bytes []byte) (chunks.DataTrackerListChunk, error) {
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerListChunk{}, err
|
return chunks.DataTrackerListChunk{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
trackers := []DataTrackerChunk{}
|
trackers := []chunks.DataTrackerChunk{}
|
||||||
if chunk.Header.HasSubchunks && chunk.Header.DataLen > 0 {
|
if chunk.Header.HasSubchunks && chunk.Header.DataLen > 0 {
|
||||||
offset := 0
|
offset := 0
|
||||||
for offset < int(chunk.Header.DataLen) {
|
for offset < int(chunk.Header.DataLen) {
|
||||||
trackerChunk, err := DecodeDataTrackerChunk(chunk.ChunkData[offset:])
|
trackerChunk, err := DecodeDataTrackerChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerListChunk{}, err
|
return chunks.DataTrackerListChunk{}, err
|
||||||
}
|
}
|
||||||
offset += 4
|
offset += 4
|
||||||
if trackerChunk.Chunk.Header.DataLen > 0 {
|
if trackerChunk.Chunk.Header.DataLen > 0 {
|
||||||
@@ -31,11 +25,11 @@ func DecodeDataTrackerListChunk(bytes []byte) (DataTrackerListChunk, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data := DataTrackerListChunkData{
|
data := chunks.DataTrackerListChunkData{
|
||||||
Trackers: trackers,
|
Trackers: trackers,
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataTrackerListChunk{
|
return chunks.DataTrackerListChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodDataTrackerListChunkDecoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.DataTrackerListChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "DataTrackerListChunk",
|
||||||
|
bytes: []byte{
|
||||||
|
1, 0, 104, 128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0,
|
||||||
|
64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12, 0, 0, 0, 128,
|
||||||
|
63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
expected: chunks.DataTrackerListChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{
|
||||||
|
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0,
|
||||||
|
0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4,
|
||||||
|
0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||||
|
6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 104, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerListChunkData{
|
||||||
|
Trackers: []chunks.DataTrackerChunk{
|
||||||
|
{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{
|
||||||
|
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0,
|
||||||
|
0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0,
|
||||||
|
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64,
|
||||||
|
64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 100, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerChunkData{
|
||||||
|
Pos: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Speed: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 1, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Ori: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 2, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: &chunks.DataTrackerStatusChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 4, Id: 3, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerStatusChunkData{
|
||||||
|
Validity: 1.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Accel: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 4, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TrgtPos: &chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 5, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Timestamp: &chunks.DataTrackerTimestampChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 8, Id: 6, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerTimestampChunkData{
|
||||||
|
Timestamp: 1234567890,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeDataTrackerListChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,35 +4,28 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DataTrackerStatusChunkData struct {
|
func DecodeDataTrackerStatusChunk(bytes []byte) (chunks.DataTrackerStatusChunk, error) {
|
||||||
Validity float32
|
|
||||||
}
|
|
||||||
|
|
||||||
type DataTrackerStatusChunk struct {
|
|
||||||
Chunk Chunk
|
|
||||||
Data DataTrackerStatusChunkData
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeDataTrackerStatusChunk(bytes []byte) (DataTrackerStatusChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerStatusChunk{}, err
|
return chunks.DataTrackerStatusChunk{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(chunk.ChunkData) < 4 {
|
if len(chunk.ChunkData) < 4 {
|
||||||
return DataTrackerStatusChunk{}, errors.New("DATA_TRACKER_STATUS chunk must be at least 4 bytes")
|
return chunks.DataTrackerStatusChunk{}, errors.New("DATA_TRACKER_STATUS chunk must be at least 4 bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
statusBits := binary.LittleEndian.Uint32(chunk.ChunkData[0:4])
|
statusBits := binary.LittleEndian.Uint32(chunk.ChunkData[0:4])
|
||||||
|
|
||||||
data := DataTrackerStatusChunkData{
|
data := chunks.DataTrackerStatusChunkData{
|
||||||
Validity: math.Float32frombits(statusBits),
|
Validity: math.Float32frombits(statusBits),
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataTrackerStatusChunk{
|
return chunks.DataTrackerStatusChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodDataTrackerStatusChunk(t *testing.T) {
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.DataTrackerStatusChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "DataTrackerStatusChunk",
|
||||||
|
bytes: []byte{3, 0, 4, 0, 0, 0, 128, 63},
|
||||||
|
expected: chunks.DataTrackerStatusChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 4, Id: 3, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerStatusChunkData{
|
||||||
|
Validity: 1.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeDataTrackerStatusChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,35 +3,28 @@ package decoders
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DataTrackerTimestampChunkData struct {
|
func DecodeDataTrackerTimestampChunk(bytes []byte) (chunks.DataTrackerTimestampChunk, error) {
|
||||||
Timestamp uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
type DataTrackerTimestampChunk struct {
|
|
||||||
Chunk Chunk
|
|
||||||
Data DataTrackerTimestampChunkData
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeDataTrackerTimestampChunk(bytes []byte) (DataTrackerTimestampChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerTimestampChunk{}, err
|
return chunks.DataTrackerTimestampChunk{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(chunk.ChunkData) < 8 {
|
if len(chunk.ChunkData) < 8 {
|
||||||
return DataTrackerTimestampChunk{}, errors.New("DATA_TRACKER_TIMESTAMP chunk must be at least 8 bytes")
|
return chunks.DataTrackerTimestampChunk{}, errors.New("DATA_TRACKER_TIMESTAMP chunk must be at least 8 bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp := binary.LittleEndian.Uint64(chunk.ChunkData[0:8])
|
timestamp := binary.LittleEndian.Uint64(chunk.ChunkData[0:8])
|
||||||
|
|
||||||
data := DataTrackerTimestampChunkData{
|
data := chunks.DataTrackerTimestampChunkData{
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataTrackerTimestampChunk{
|
return chunks.DataTrackerTimestampChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodDataTrackerTimestampChunk(t *testing.T) {
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.DataTrackerTimestampChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "DataTrackerTimestampChunk",
|
||||||
|
bytes: []byte{6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0},
|
||||||
|
expected: chunks.DataTrackerTimestampChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 8, Id: 6, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerTimestampChunkData{
|
||||||
|
Timestamp: 1234567890,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeDataTrackerTimestampChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,41 +4,32 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DataTrackerXYZChunkData struct {
|
func DecodeDataTrackerXYZChunk(bytes []byte) (chunks.DataTrackerXYZChunk, error) {
|
||||||
X float32
|
|
||||||
Y float32
|
|
||||||
Z float32
|
|
||||||
}
|
|
||||||
|
|
||||||
type DataTrackerXYZChunk struct {
|
|
||||||
Chunk Chunk
|
|
||||||
Data DataTrackerXYZChunkData
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeDataTrackerXYZChunk(bytes []byte) (DataTrackerXYZChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DataTrackerXYZChunk{}, err
|
return chunks.DataTrackerXYZChunk{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(chunk.ChunkData) < 12 {
|
if len(chunk.ChunkData) < 12 {
|
||||||
return DataTrackerXYZChunk{}, errors.New("DATA_TRACKER_XYZ chunk must be at least 12 bytes")
|
return chunks.DataTrackerXYZChunk{}, errors.New("DATA_TRACKER_XYZ chunk must be at least 12 bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
xBits := binary.LittleEndian.Uint32(chunk.ChunkData[0:4])
|
xBits := binary.LittleEndian.Uint32(chunk.ChunkData[0:4])
|
||||||
yBits := binary.LittleEndian.Uint32(chunk.ChunkData[4:8])
|
yBits := binary.LittleEndian.Uint32(chunk.ChunkData[4:8])
|
||||||
zBits := binary.LittleEndian.Uint32(chunk.ChunkData[8:12])
|
zBits := binary.LittleEndian.Uint32(chunk.ChunkData[8:12])
|
||||||
|
|
||||||
data := DataTrackerXYZChunkData{
|
data := chunks.DataTrackerXYZChunkData{
|
||||||
X: math.Float32frombits(xBits),
|
X: math.Float32frombits(xBits),
|
||||||
Y: math.Float32frombits(yBits),
|
Y: math.Float32frombits(yBits),
|
||||||
Z: math.Float32frombits(zBits),
|
Z: math.Float32frombits(zBits),
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataTrackerXYZChunk{
|
return chunks.DataTrackerXYZChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodDataTrackerXYZChunk(t *testing.T) {
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.DataTrackerXYZChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "DataTrackerPosChunk",
|
||||||
|
bytes: []byte{0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
expected: chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "DataTrackerSpeedChunk",
|
||||||
|
bytes: []byte{1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
expected: chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 1, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "DataTrackerOriChunk",
|
||||||
|
bytes: []byte{2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
expected: chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 2, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "DataTrackerAccelChunk",
|
||||||
|
bytes: []byte{4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
expected: chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 4, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "DataTrackerTrgtPosChunk",
|
||||||
|
bytes: []byte{5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
expected: chunks.DataTrackerXYZChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 5, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1.0,
|
||||||
|
Y: 2.0,
|
||||||
|
Z: 3.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeDataTrackerXYZChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,25 +3,16 @@ package decoders
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InfoPacketChunkData struct {
|
func DecodeInfoPacketChunk(bytes []byte) (chunks.InfoPacketChunk, error) {
|
||||||
PacketHeader *PacketHeaderChunk
|
|
||||||
SystemName *InfoSystemNameChunk
|
|
||||||
TrackerList *InfoTrackerListChunk
|
|
||||||
}
|
|
||||||
|
|
||||||
type InfoPacketChunk struct {
|
|
||||||
Data InfoPacketChunkData
|
|
||||||
Chunk Chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeInfoPacketChunk(bytes []byte) (InfoPacketChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoPacketChunk{}, err
|
return chunks.InfoPacketChunk{}, err
|
||||||
}
|
}
|
||||||
data := InfoPacketChunkData{}
|
data := chunks.InfoPacketChunkData{}
|
||||||
|
|
||||||
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
||||||
offset := 0
|
offset := 0
|
||||||
@@ -31,7 +22,7 @@ func DecodeInfoPacketChunk(bytes []byte) (InfoPacketChunk, error) {
|
|||||||
case 0x0000:
|
case 0x0000:
|
||||||
packet_header, err := DecodePacketHeaderChunk(chunk.ChunkData[offset:])
|
packet_header, err := DecodePacketHeaderChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoPacketChunk{}, err
|
return chunks.InfoPacketChunk{}, err
|
||||||
}
|
}
|
||||||
data.PacketHeader = &packet_header
|
data.PacketHeader = &packet_header
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -41,7 +32,7 @@ func DecodeInfoPacketChunk(bytes []byte) (InfoPacketChunk, error) {
|
|||||||
case 0x0001:
|
case 0x0001:
|
||||||
system_name, err := DecodeInfoSystemNameChunk(chunk.ChunkData[offset:])
|
system_name, err := DecodeInfoSystemNameChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoPacketChunk{}, err
|
return chunks.InfoPacketChunk{}, err
|
||||||
}
|
}
|
||||||
data.SystemName = &system_name
|
data.SystemName = &system_name
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -51,7 +42,7 @@ func DecodeInfoPacketChunk(bytes []byte) (InfoPacketChunk, error) {
|
|||||||
case 0x0002:
|
case 0x0002:
|
||||||
tracker_list, err := DecodeInfoTrackerListChunk(chunk.ChunkData[offset:])
|
tracker_list, err := DecodeInfoTrackerListChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoPacketChunk{}, err
|
return chunks.InfoPacketChunk{}, err
|
||||||
}
|
}
|
||||||
data.TrackerList = &tracker_list
|
data.TrackerList = &tracker_list
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -65,7 +56,7 @@ func DecodeInfoPacketChunk(bytes []byte) (InfoPacketChunk, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return InfoPacketChunk{
|
return chunks.InfoPacketChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodInfoPacketChunkDecoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.InfoPacketChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "InfoPacketChunk",
|
||||||
|
bytes: []byte{
|
||||||
|
86, 103, 51, 128, 0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 10, 0, 80, 83, 78, 32, 83, 101,
|
||||||
|
114, 118, 101, 114, 2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||||
|
},
|
||||||
|
expected: chunks.InfoPacketChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{
|
||||||
|
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101,
|
||||||
|
114, 2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||||
|
},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 51, Id: 26454, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoPacketChunkData{
|
||||||
|
PacketHeader: &chunks.PacketHeaderChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.PacketHeaderChunkData{
|
||||||
|
PacketTimestamp: 1234567890,
|
||||||
|
VersionHigh: 2,
|
||||||
|
VersionLow: 3,
|
||||||
|
FrameId: 1,
|
||||||
|
FramePacketCount: 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SystemName: &chunks.InfoSystemNameChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{80, 83, 78, 32, 83, 101, 114, 118, 101, 114},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 10, Id: 1, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoSystemNameChunkData{
|
||||||
|
SystemName: "PSN Server",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TrackerList: &chunks.InfoTrackerListChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 17, Id: 2, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerListChunkData{
|
||||||
|
Trackers: []chunks.InfoTrackerChunk{
|
||||||
|
{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerChunkData{
|
||||||
|
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerNameChunkData{
|
||||||
|
TrackerName: "Tracker 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "empty InfoPacketChunk",
|
||||||
|
bytes: []byte{
|
||||||
|
0x56, 0x67, 0x22, 0x80, 0x00, 0x00, 0x0C, 0x00, 0x3D, 0x2C, 0x91, 0xDB, 0x9A, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||||
|
0x01, 0x01, 0x00, 0x0A, 0x00, 0x50, 0x53, 0x4E, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x02, 0x00, 0x00, 0x80,
|
||||||
|
},
|
||||||
|
expected: chunks.InfoPacketChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{
|
||||||
|
0x00, 0x00, 0x0C, 0x00, 0x3D, 0x2C, 0x91, 0xDB, 0x9A, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||||
|
0x01, 0x01, 0x00, 0x0A, 0x00, 0x50, 0x53, 0x4E, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x02, 0x00, 0x00, 0x80,
|
||||||
|
},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 34, Id: 26454, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoPacketChunkData{
|
||||||
|
PacketHeader: &chunks.PacketHeaderChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0x3D, 0x2C, 0x91, 0xDB, 0x9A, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.PacketHeaderChunkData{
|
||||||
|
PacketTimestamp: 1764620315709,
|
||||||
|
VersionHigh: 2,
|
||||||
|
VersionLow: 0,
|
||||||
|
FrameId: 0,
|
||||||
|
FramePacketCount: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SystemName: &chunks.InfoSystemNameChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{80, 83, 78, 32, 83, 101, 114, 118, 101, 114},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 10, Id: 1, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoSystemNameChunkData{
|
||||||
|
SystemName: "PSN Server",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TrackerList: &chunks.InfoTrackerListChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 0, Id: 2, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerListChunkData{
|
||||||
|
Trackers: []chunks.InfoTrackerChunk{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeInfoPacketChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +1,19 @@
|
|||||||
package decoders
|
package decoders
|
||||||
|
|
||||||
type InfoSystemNameChunkData struct {
|
import "github.com/jwetzell/psn-go/internal/chunks"
|
||||||
SystemName string
|
|
||||||
}
|
|
||||||
|
|
||||||
type InfoSystemNameChunk struct {
|
func DecodeInfoSystemNameChunk(bytes []byte) (chunks.InfoSystemNameChunk, error) {
|
||||||
Data InfoSystemNameChunkData
|
|
||||||
Chunk Chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeInfoSystemNameChunk(bytes []byte) (InfoSystemNameChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoSystemNameChunk{}, err
|
return chunks.InfoSystemNameChunk{}, err
|
||||||
}
|
}
|
||||||
data := InfoSystemNameChunkData{}
|
data := chunks.InfoSystemNameChunkData{}
|
||||||
|
|
||||||
if chunk.Header.DataLen > 0 {
|
if chunk.Header.DataLen > 0 {
|
||||||
data.SystemName = string(chunk.ChunkData[0:chunk.Header.DataLen])
|
data.SystemName = string(chunk.ChunkData[0:chunk.Header.DataLen])
|
||||||
}
|
}
|
||||||
|
|
||||||
return InfoSystemNameChunk{
|
return chunks.InfoSystemNameChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodInfoSystemNameChunkDecoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.InfoSystemNameChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "InfoSystemNameChunk",
|
||||||
|
bytes: []byte{
|
||||||
|
1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101, 114,
|
||||||
|
},
|
||||||
|
expected: chunks.InfoSystemNameChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{80, 83, 78, 32, 83, 101, 114, 118, 101, 114},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 10, Id: 1, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoSystemNameChunkData{
|
||||||
|
SystemName: "PSN Server",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeInfoSystemNameChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,23 +3,16 @@ package decoders
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InfoTrackerChunkData struct {
|
func DecodeInfoTrackerChunk(bytes []byte) (chunks.InfoTrackerChunk, error) {
|
||||||
TrackerName *InfoTrackerNameChunk
|
|
||||||
}
|
|
||||||
|
|
||||||
type InfoTrackerChunk struct {
|
|
||||||
Data InfoTrackerChunkData
|
|
||||||
Chunk Chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeInfoTrackerChunk(bytes []byte) (InfoTrackerChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoTrackerChunk{}, err
|
return chunks.InfoTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
data := InfoTrackerChunkData{}
|
data := chunks.InfoTrackerChunkData{}
|
||||||
|
|
||||||
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
||||||
offset := 0
|
offset := 0
|
||||||
@@ -29,7 +22,7 @@ func DecodeInfoTrackerChunk(bytes []byte) (InfoTrackerChunk, error) {
|
|||||||
case 0x0000:
|
case 0x0000:
|
||||||
tracker_name, err := DecodeInfoTrackerNameChunk(chunk.ChunkData[offset:])
|
tracker_name, err := DecodeInfoTrackerNameChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoTrackerChunk{}, err
|
return chunks.InfoTrackerChunk{}, err
|
||||||
}
|
}
|
||||||
data.TrackerName = &tracker_name
|
data.TrackerName = &tracker_name
|
||||||
offset += 4
|
offset += 4
|
||||||
@@ -42,7 +35,7 @@ func DecodeInfoTrackerChunk(bytes []byte) (InfoTrackerChunk, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return InfoTrackerChunk{
|
return chunks.InfoTrackerChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodInfoTrackerChunkDecoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.InfoTrackerChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "InfoTrackerChunk",
|
||||||
|
bytes: []byte{
|
||||||
|
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||||
|
},
|
||||||
|
expected: chunks.InfoTrackerChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerChunkData{
|
||||||
|
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerNameChunkData{
|
||||||
|
TrackerName: "Tracker 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeInfoTrackerChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,27 +1,20 @@
|
|||||||
package decoders
|
package decoders
|
||||||
|
|
||||||
type InfoTrackerListChunkData struct {
|
import "github.com/jwetzell/psn-go/internal/chunks"
|
||||||
Trackers []InfoTrackerChunk
|
|
||||||
}
|
|
||||||
|
|
||||||
type InfoTrackerListChunk struct {
|
func DecodeInfoTrackerListChunk(bytes []byte) (chunks.InfoTrackerListChunk, error) {
|
||||||
Chunk Chunk
|
|
||||||
Data InfoTrackerListChunkData
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeInfoTrackerListChunk(bytes []byte) (InfoTrackerListChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoTrackerListChunk{}, err
|
return chunks.InfoTrackerListChunk{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
trackers := []InfoTrackerChunk{}
|
trackers := []chunks.InfoTrackerChunk{}
|
||||||
if chunk.Header.HasSubchunks && chunk.Header.DataLen > 0 {
|
if chunk.Header.HasSubchunks && chunk.Header.DataLen > 0 {
|
||||||
offset := 0
|
offset := 0
|
||||||
for offset < int(chunk.Header.DataLen) {
|
for offset < int(chunk.Header.DataLen) {
|
||||||
trackerChunk, err := DecodeInfoTrackerChunk(chunk.ChunkData[offset:])
|
trackerChunk, err := DecodeInfoTrackerChunk(chunk.ChunkData[offset:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoTrackerListChunk{}, err
|
return chunks.InfoTrackerListChunk{}, err
|
||||||
}
|
}
|
||||||
offset += 4
|
offset += 4
|
||||||
if trackerChunk.Chunk.Header.DataLen > 0 {
|
if trackerChunk.Chunk.Header.DataLen > 0 {
|
||||||
@@ -31,11 +24,11 @@ func DecodeInfoTrackerListChunk(bytes []byte) (InfoTrackerListChunk, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data := InfoTrackerListChunkData{
|
data := chunks.InfoTrackerListChunkData{
|
||||||
Trackers: trackers,
|
Trackers: trackers,
|
||||||
}
|
}
|
||||||
|
|
||||||
return InfoTrackerListChunk{
|
return chunks.InfoTrackerListChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodInfoTrackerListChunkDecoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.InfoTrackerListChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "InfoTrackerListChunk",
|
||||||
|
bytes: []byte{
|
||||||
|
2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||||
|
},
|
||||||
|
expected: chunks.InfoTrackerListChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 17, Id: 2, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerListChunkData{
|
||||||
|
Trackers: []chunks.InfoTrackerChunk{
|
||||||
|
{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerChunkData{
|
||||||
|
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerNameChunkData{
|
||||||
|
TrackerName: "Tracker 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeInfoTrackerListChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,21 @@
|
|||||||
package decoders
|
package decoders
|
||||||
|
|
||||||
type InfoTrackerNameChunkData struct {
|
import "github.com/jwetzell/psn-go/internal/chunks"
|
||||||
TrackerName string
|
|
||||||
}
|
|
||||||
|
|
||||||
type InfoTrackerNameChunk struct {
|
func DecodeInfoTrackerNameChunk(bytes []byte) (chunks.InfoTrackerNameChunk, error) {
|
||||||
Data InfoTrackerNameChunkData
|
|
||||||
Chunk Chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeInfoTrackerNameChunk(bytes []byte) (InfoTrackerNameChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InfoTrackerNameChunk{}, err
|
return chunks.InfoTrackerNameChunk{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := InfoTrackerNameChunkData{}
|
data := chunks.InfoTrackerNameChunkData{}
|
||||||
|
|
||||||
if chunk.Header.DataLen > 0 {
|
if chunk.Header.DataLen > 0 {
|
||||||
data.TrackerName = string(chunk.ChunkData[0:chunk.Header.DataLen])
|
data.TrackerName = string(chunk.ChunkData[0:chunk.Header.DataLen])
|
||||||
}
|
}
|
||||||
|
|
||||||
return InfoTrackerNameChunk{
|
return chunks.InfoTrackerNameChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodInfoTrackerNameChunkDecoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.InfoTrackerNameChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "InfoTrackerNameChunk",
|
||||||
|
bytes: []byte{
|
||||||
|
0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||||
|
},
|
||||||
|
expected: chunks.InfoTrackerNameChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerNameChunkData{
|
||||||
|
TrackerName: "Tracker 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodeInfoTrackerNameChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,15 @@
|
|||||||
package decoders
|
package decoders
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
type PacketHeaderChunkData struct {
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
PacketTimestamp uint64
|
)
|
||||||
VersionHigh uint8
|
|
||||||
VersionLow uint8
|
|
||||||
FrameId uint8
|
|
||||||
FramePacketCount uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
type PacketHeaderChunk struct {
|
func DecodePacketHeaderChunk(bytes []byte) (chunks.PacketHeaderChunk, error) {
|
||||||
Chunk Chunk
|
|
||||||
Data PacketHeaderChunkData
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodePacketHeaderChunk(bytes []byte) (PacketHeaderChunk, error) {
|
|
||||||
chunk, err := DecodeChunk(bytes)
|
chunk, err := DecodeChunk(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return PacketHeaderChunk{}, err
|
return chunks.PacketHeaderChunk{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
packet_timestamp := binary.LittleEndian.Uint64(chunk.ChunkData[0:8])
|
packet_timestamp := binary.LittleEndian.Uint64(chunk.ChunkData[0:8])
|
||||||
@@ -27,7 +18,7 @@ func DecodePacketHeaderChunk(bytes []byte) (PacketHeaderChunk, error) {
|
|||||||
frame_id := chunk.ChunkData[10]
|
frame_id := chunk.ChunkData[10]
|
||||||
frame_packet_count := chunk.ChunkData[11]
|
frame_packet_count := chunk.ChunkData[11]
|
||||||
|
|
||||||
data := PacketHeaderChunkData{
|
data := chunks.PacketHeaderChunkData{
|
||||||
PacketTimestamp: packet_timestamp,
|
PacketTimestamp: packet_timestamp,
|
||||||
VersionHigh: version_high,
|
VersionHigh: version_high,
|
||||||
VersionLow: version_low,
|
VersionLow: version_low,
|
||||||
@@ -35,7 +26,7 @@ func DecodePacketHeaderChunk(bytes []byte) (PacketHeaderChunk, error) {
|
|||||||
FramePacketCount: frame_packet_count,
|
FramePacketCount: frame_packet_count,
|
||||||
}
|
}
|
||||||
|
|
||||||
return PacketHeaderChunk{
|
return chunks.PacketHeaderChunk{
|
||||||
Chunk: chunk,
|
Chunk: chunk,
|
||||||
Data: data,
|
Data: data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package decoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoodPacketHeaderChunkDecoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
bytes []byte
|
||||||
|
expected chunks.PacketHeaderChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "PacketHeaderChunk",
|
||||||
|
bytes: []byte{
|
||||||
|
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
|
||||||
|
},
|
||||||
|
expected: chunks.PacketHeaderChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.PacketHeaderChunkData{
|
||||||
|
PacketTimestamp: 1234567890,
|
||||||
|
VersionHigh: 2,
|
||||||
|
VersionLow: 3,
|
||||||
|
FrameId: 1,
|
||||||
|
FramePacketCount: 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual, err := DecodePacketHeaderChunk(testCase.bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to decode chunk properly, error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to decode chunk properly, expected: %+v, actual: %+v", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
[]byte("0000")
|
||||||
@@ -1,18 +1,17 @@
|
|||||||
package encoders
|
package encoders
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jwetzell/psn-go/internal/decoders"
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestChunkEncoding(t *testing.T) {
|
func TestChunkEncoding(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
description string
|
description string
|
||||||
expected []byte
|
expected []byte
|
||||||
chunk decoders.Chunk
|
chunk chunks.Chunk
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
description: "info packet",
|
description: "info packet",
|
||||||
@@ -21,8 +20,8 @@ func TestChunkEncoding(t *testing.T) {
|
|||||||
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
||||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
||||||
},
|
},
|
||||||
chunk: decoders.Chunk{
|
chunk: chunks.Chunk{
|
||||||
Header: decoders.ChunkHeader{
|
Header: chunks.ChunkHeader{
|
||||||
Id: uint16(26454),
|
Id: uint16(26454),
|
||||||
DataLen: uint16(52),
|
DataLen: uint16(52),
|
||||||
HasSubchunks: true,
|
HasSubchunks: true,
|
||||||
@@ -41,8 +40,8 @@ func TestChunkEncoding(t *testing.T) {
|
|||||||
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
||||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||||
},
|
},
|
||||||
chunk: decoders.Chunk{
|
chunk: chunks.Chunk{
|
||||||
Header: decoders.ChunkHeader{
|
Header: chunks.ChunkHeader{
|
||||||
Id: uint16(26453),
|
Id: uint16(26453),
|
||||||
DataLen: uint16(40),
|
DataLen: uint16(40),
|
||||||
HasSubchunks: true,
|
HasSubchunks: true,
|
||||||
@@ -57,13 +56,30 @@ func TestChunkEncoding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeChunk(testCase.chunk.Header.Id, testCase.chunk.ChunkData, testCase.chunk.Header.HasSubchunks)
|
||||||
|
|
||||||
actual := EncodeChunk(testCase.chunk.Header.Id, testCase.chunk.ChunkData, testCase.chunk.Header.HasSubchunks)
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
}
|
||||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
})
|
||||||
fmt.Printf("expected: %v\n", testCase.expected)
|
}
|
||||||
fmt.Printf("actual: %v\n", actual)
|
}
|
||||||
}
|
|
||||||
|
func BenchmarkChunkEncoding(b *testing.B) {
|
||||||
|
chunk := chunks.Chunk{
|
||||||
|
Header: chunks.ChunkHeader{
|
||||||
|
Id: uint16(26453),
|
||||||
|
DataLen: uint16(40),
|
||||||
|
HasSubchunks: true,
|
||||||
|
},
|
||||||
|
ChunkData: []byte{
|
||||||
|
0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||||
|
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
||||||
|
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for b.Loop() {
|
||||||
|
EncodeChunk(chunk.Header.Id, chunk.ChunkData, chunk.Header.HasSubchunks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDataTrackerAccelChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.DataTrackerXYZChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "basic acceleration",
|
||||||
|
expected: []byte{
|
||||||
|
4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||||
|
},
|
||||||
|
data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1,
|
||||||
|
Y: 2,
|
||||||
|
Z: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeDataTrackerAccelChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDataTrackerOriChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.DataTrackerXYZChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "basic orientation",
|
||||||
|
expected: []byte{
|
||||||
|
2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||||
|
},
|
||||||
|
data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1,
|
||||||
|
Y: 2,
|
||||||
|
Z: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeDataTrackerOriChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDataTrackerPosChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.DataTrackerXYZChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "basic position",
|
||||||
|
expected: []byte{
|
||||||
|
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||||
|
},
|
||||||
|
data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1,
|
||||||
|
Y: 2,
|
||||||
|
Z: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeDataTrackerPosChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDataTrackerSpeedChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.DataTrackerXYZChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "basic speed",
|
||||||
|
expected: []byte{
|
||||||
|
1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||||
|
},
|
||||||
|
data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1,
|
||||||
|
Y: 2,
|
||||||
|
Z: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeDataTrackerSpeedChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDataTrackerStatusChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.DataTrackerStatusChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "basic status",
|
||||||
|
expected: []byte{
|
||||||
|
3, 0, 4, 0, 0, 0, 128, 63,
|
||||||
|
},
|
||||||
|
data: chunks.DataTrackerStatusChunkData{
|
||||||
|
Validity: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeDataTrackerStatusChunk(testCase.data.Validity)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDataTrackerTimestampChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.DataTrackerTimestampChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "basic timestamp",
|
||||||
|
expected: []byte{
|
||||||
|
6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
data: chunks.DataTrackerTimestampChunkData{
|
||||||
|
Timestamp: 1234567890,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeDataTrackerTimestampChunk(testCase.data.Timestamp)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDataTrackerTrgtPosChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.DataTrackerXYZChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "basic target position",
|
||||||
|
expected: []byte{
|
||||||
|
5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||||
|
},
|
||||||
|
data: chunks.DataTrackerXYZChunkData{
|
||||||
|
X: 1,
|
||||||
|
Y: 2,
|
||||||
|
Z: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
|
||||||
|
actual := EncodeDataTrackerTrgtPosChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInfoSystemNameChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.InfoSystemNameChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "InfoSystemNameChunk",
|
||||||
|
expected: []byte{
|
||||||
|
1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101, 114,
|
||||||
|
},
|
||||||
|
data: chunks.InfoSystemNameChunkData{
|
||||||
|
SystemName: "PSN Server",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeInfoSystemNameChunk(testCase.data.SystemName)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInfoTrackerChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
chunk chunks.InfoTrackerChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "InfoTrackerChunk",
|
||||||
|
expected: []byte{
|
||||||
|
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||||
|
},
|
||||||
|
chunk: chunks.InfoTrackerChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerChunkData{
|
||||||
|
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerNameChunkData{
|
||||||
|
TrackerName: "Tracker 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeInfoTrackerChunk(testCase.chunk.Chunk.Header.Id, EncodeInfoTrackerNameChunk(testCase.chunk.Data.TrackerName.Data.TrackerName))
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInfoTrackerListChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
chunk chunks.InfoTrackerListChunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "InfoTrackerListChunk",
|
||||||
|
expected: []byte{
|
||||||
|
2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||||
|
},
|
||||||
|
chunk: chunks.InfoTrackerListChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 17, Id: 2, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerListChunkData{
|
||||||
|
Trackers: []chunks.InfoTrackerChunk{
|
||||||
|
{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerChunkData{
|
||||||
|
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||||
|
Chunk: chunks.Chunk{
|
||||||
|
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||||
|
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||||
|
},
|
||||||
|
Data: chunks.InfoTrackerNameChunkData{
|
||||||
|
TrackerName: "Tracker 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
trackerChunks := [][]byte{}
|
||||||
|
for _, tracker := range testCase.chunk.Data.Trackers {
|
||||||
|
trackerChunks = append(trackerChunks, EncodeInfoTrackerChunk(tracker.Chunk.Header.Id, EncodeInfoTrackerNameChunk(tracker.Data.TrackerName.Data.TrackerName)))
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := EncodeInfoTrackerListChunk(trackerChunks)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInfoTrackerNameChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.InfoTrackerNameChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "InfoTrackerNameChunk",
|
||||||
|
expected: []byte{
|
||||||
|
0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||||
|
},
|
||||||
|
data: chunks.InfoTrackerNameChunkData{
|
||||||
|
TrackerName: "Tracker 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodeInfoTrackerNameChunk(testCase.data.TrackerName)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPacketHeaderChunkEncoding(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
expected []byte
|
||||||
|
data chunks.PacketHeaderChunkData
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "PacketHeaderChunk",
|
||||||
|
expected: []byte{
|
||||||
|
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
|
||||||
|
},
|
||||||
|
data: chunks.PacketHeaderChunkData{
|
||||||
|
PacketTimestamp: 1234567890,
|
||||||
|
VersionHigh: 2,
|
||||||
|
VersionLow: 3,
|
||||||
|
FrameId: 1,
|
||||||
|
FramePacketCount: 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
|
actual := EncodePacketHeaderChunk(testCase.data.PacketTimestamp, testCase.data.VersionHigh, testCase.data.VersionLow, testCase.data.FrameId, testCase.data.FramePacketCount)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||||
|
t.Errorf("failed to encode chunk properly, expected: %v, actual: %v\n", testCase.expected, actual)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-5
@@ -1,7 +1,7 @@
|
|||||||
package psn
|
package psn
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jwetzell/psn-go/internal/decoders"
|
"github.com/jwetzell/psn-go/internal/chunks"
|
||||||
"github.com/jwetzell/psn-go/internal/encoders"
|
"github.com/jwetzell/psn-go/internal/encoders"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -138,12 +138,12 @@ func (t *Tracker) GetInfoChunk() []byte {
|
|||||||
return encoders.EncodeInfoTrackerChunk(t.Id, encoders.EncodeInfoTrackerNameChunk(t.Name))
|
return encoders.EncodeInfoTrackerChunk(t.Id, encoders.EncodeInfoTrackerNameChunk(t.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracker) UpdateInfo(infoTrackerChunk decoders.InfoTrackerChunk) {
|
func (t *Tracker) UpdateInfo(infoTrackerChunk chunks.InfoTrackerChunk) {
|
||||||
t.Id = infoTrackerChunk.Chunk.Header.Id
|
t.Id = infoTrackerChunk.Chunk.Header.Id
|
||||||
t.Name = infoTrackerChunk.Data.TrackerName.Data.TrackerName
|
t.Name = infoTrackerChunk.Data.TrackerName.Data.TrackerName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracker) UpdateData(dataTrackerChunk decoders.DataTrackerChunk) {
|
func (t *Tracker) UpdateData(dataTrackerChunk chunks.DataTrackerChunk) {
|
||||||
if dataTrackerChunk.Data.Pos != nil {
|
if dataTrackerChunk.Data.Pos != nil {
|
||||||
t.SetPos(dataTrackerChunk.Data.Pos.Data.X, dataTrackerChunk.Data.Pos.Data.Y, dataTrackerChunk.Data.Pos.Data.Z)
|
t.SetPos(dataTrackerChunk.Data.Pos.Data.X, dataTrackerChunk.Data.Pos.Data.Y, dataTrackerChunk.Data.Pos.Data.Z)
|
||||||
}
|
}
|
||||||
@@ -173,13 +173,13 @@ func (t *Tracker) UpdateData(dataTrackerChunk decoders.DataTrackerChunk) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TrackerFromInfo(infoTrackerChunk decoders.InfoTrackerChunk) *Tracker {
|
func TrackerFromInfo(infoTrackerChunk chunks.InfoTrackerChunk) *Tracker {
|
||||||
var tracker Tracker
|
var tracker Tracker
|
||||||
tracker.UpdateInfo(infoTrackerChunk)
|
tracker.UpdateInfo(infoTrackerChunk)
|
||||||
return &tracker
|
return &tracker
|
||||||
}
|
}
|
||||||
|
|
||||||
func TrackerFromData(dataTrackerChunk decoders.DataTrackerChunk) *Tracker {
|
func TrackerFromData(dataTrackerChunk chunks.DataTrackerChunk) *Tracker {
|
||||||
var tracker Tracker
|
var tracker Tracker
|
||||||
tracker.UpdateData(dataTrackerChunk)
|
tracker.UpdateData(dataTrackerChunk)
|
||||||
return &tracker
|
return &tracker
|
||||||
|
|||||||
Reference in New Issue
Block a user