Skip to content

Commit

Permalink
Added better DataHolder type handling
Browse files Browse the repository at this point in the history
  • Loading branch information
jonbarrow committed May 9, 2022
1 parent 69e9aa2 commit 35414b9
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 26 deletions.
111 changes: 85 additions & 26 deletions nex_types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nex

import (
"reflect"
"strings"
"time"
)
Expand All @@ -27,6 +28,19 @@ type Data struct {
*Structure
}

// ExtractFromStream does nothing for Data
func (data *Data) ExtractFromStream(stream *StreamIn) error {
// Basically do nothing. Does a relative seek with 0
stream.SeekByte(0, true)

return nil
}

// Bytes does nothing for Data
func (data *Data) Bytes(stream *StreamOut) []byte {
return stream.Bytes()
}

// NewData returns a new Data Structure
func NewData() *Data {
structure := &Structure{}
Expand All @@ -35,19 +49,84 @@ func NewData() *Data {
return data
}

// ExtractFromStream does nothing for Data
func (data *Data) ExtractFromStream(stream *StreamIn) error {
// Basically do nothing. Does a relative seek with 0
stream.SeekByte(0, true)
var dataHolderKnownObjects = make(map[string]StructureInterface)

func RegisterDataHolderType(structure StructureInterface) {
name := reflect.TypeOf(structure).Elem().Name()
dataHolderKnownObjects[name] = structure
}

// DataHolder represents a structure which can hold any other structure
type DataHolder struct {
typeName string
length1 uint32 // length of data including length2
length2 uint32 // length of the actual structure
objectData StructureInterface
}

func (dataHolder *DataHolder) TypeName() string {
return dataHolder.typeName
}

func (dataHolder *DataHolder) SetTypeName(typeName string) {
dataHolder.typeName = typeName
}

func (dataHolder *DataHolder) ObjectData() StructureInterface {
return dataHolder.objectData
}

func (dataHolder *DataHolder) SetObjectData(objectData StructureInterface) {
dataHolder.objectData = objectData
}

// ExtractFromStream extracts a DataHolder structure from a stream
func (dataHolder *DataHolder) ExtractFromStream(stream *StreamIn) error {
// TODO: Error checks
dataHolder.typeName, _ = stream.ReadString()
dataHolder.length1 = stream.ReadUInt32LE()
dataHolder.length2 = stream.ReadUInt32LE()

newObjectInstance := reflect.New(reflect.TypeOf(dataHolderKnownObjects[dataHolder.typeName]).Elem()).Interface().(StructureInterface)

dataHolder.objectData, _ = stream.ReadStructure(newObjectInstance)

return nil
}

// Bytes does nothing for Data
func (data *Data) Bytes(stream *StreamOut) []byte {
func (dataHolder *DataHolder) Bytes(stream *StreamOut) []byte {
content := dataHolder.objectData.Bytes(NewStreamOut(stream.Server))

/*
Technically this way of encoding a DataHolder is "wrong".
It implies the structure of DataHolder is:
- Name (string)
- Length+4 (uint32)
- Content (Buffer)
However the structure as defined by the official NEX library is:
- Name (string)
- Length+4 (uint32)
- Length (uint32)
- Content (bytes)
It is convenient to treat the last 2 fields as a Buffer type, but
it should be noted that this is not actually the case.
*/
stream.WriteString(dataHolder.typeName)
stream.WriteUInt32LE(uint32(len(content) + 4))
stream.WriteBuffer(content)

return stream.Bytes()
}

// NewDataHolder returns a new DataHolder
func NewDataHolder() *DataHolder {
return &DataHolder{}
}

// RVConnectionData represents a nex RVConnectionData type
type RVConnectionData struct {
stationURL string
Expand Down Expand Up @@ -475,23 +554,3 @@ func (resultRange *ResultRange) ExtractFromStream(stream *StreamIn) error {
func NewResultRange() *ResultRange {
return &ResultRange{}
}

type DataHolder struct {
Name string
Object StructureInterface
}

func (dataholder *DataHolder) Bytes(stream *StreamOut) []byte {
content := dataholder.Object.Bytes(NewStreamOut(stream.Server))

stream.WriteString(dataholder.Name)
stream.WriteUInt32LE(uint32(len(content) + 4))
stream.WriteBuffer(content)

return stream.Bytes()
}

// NewDataHolder returns a new DataHolder
func NewDataHolder() *DataHolder {
return &DataHolder{}
}
8 changes: 8 additions & 0 deletions stream_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ func (stream *StreamIn) ReadDateTime() *DateTime {
return NewDateTime(stream.ReadUInt64LE())
}

// ReadDataHolder reads a DataHolder type
func (stream *StreamIn) ReadDataHolder() *DataHolder {
dataHolder := NewDataHolder()
dataHolder.ExtractFromStream(stream)

return dataHolder
}

// ReadListUInt8 reads a list of uint8 types
func (stream *StreamIn) ReadListUInt8() []uint8 {
length := stream.ReadUInt32LE()
Expand Down

0 comments on commit 35414b9

Please sign in to comment.