mirror of
https://github.com/PretendoNetwork/nex-go.git
synced 2025-04-02 11:02:14 -04:00
928 lines
25 KiB
Go
928 lines
25 KiB
Go
package nex
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
|
|
crunch "github.com/superwhiskers/crunch/v3"
|
|
)
|
|
|
|
// StreamIn is an input stream abstraction of github.com/superwhiskers/crunch with nex type support
|
|
type StreamIn struct {
|
|
*crunch.Buffer
|
|
Server *Server
|
|
}
|
|
|
|
// ReadBool reads a bool
|
|
func (stream *StreamIn) ReadBool() (bool, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 1 {
|
|
return false, errors.New("Not enough data to read bool")
|
|
}
|
|
|
|
return stream.ReadByteNext() == 1, nil
|
|
}
|
|
|
|
// ReadUInt8 reads a uint8
|
|
func (stream *StreamIn) ReadUInt8() (uint8, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 1 {
|
|
return 0, errors.New("Not enough data to read uint8")
|
|
}
|
|
|
|
return uint8(stream.ReadByteNext()), nil
|
|
}
|
|
|
|
// ReadInt8 reads a uint8
|
|
func (stream *StreamIn) ReadInt8() (int8, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 1 {
|
|
return 0, errors.New("Not enough data to read int8")
|
|
}
|
|
|
|
return int8(stream.ReadByteNext()), nil
|
|
}
|
|
|
|
// ReadUInt16LE reads a Little-Endian encoded uint16
|
|
func (stream *StreamIn) ReadUInt16LE() (uint16, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 2 {
|
|
return 0, errors.New("Not enough data to read uint16")
|
|
}
|
|
|
|
return stream.ReadU16LENext(1)[0], nil
|
|
}
|
|
|
|
// ReadUInt16BE reads a Big-Endian encoded uint16
|
|
func (stream *StreamIn) ReadUInt16BE() (uint16, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 2 {
|
|
return 0, errors.New("Not enough data to read uint16")
|
|
}
|
|
|
|
return stream.ReadU16BENext(1)[0], nil
|
|
}
|
|
|
|
// ReadInt16LE reads a Little-Endian encoded int16
|
|
func (stream *StreamIn) ReadInt16LE() (int16, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 2 {
|
|
return 0, errors.New("Not enough data to read int16")
|
|
}
|
|
|
|
return int16(stream.ReadU16LENext(1)[0]), nil
|
|
}
|
|
|
|
// ReadInt16BE reads a Big-Endian encoded int16
|
|
func (stream *StreamIn) ReadInt16BE() (int16, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 2 {
|
|
return 0, errors.New("Not enough data to read int16")
|
|
}
|
|
|
|
return int16(stream.ReadU16BENext(1)[0]), nil
|
|
}
|
|
|
|
// ReadUInt32LE reads a Little-Endian encoded uint32
|
|
func (stream *StreamIn) ReadUInt32LE() (uint32, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 4 {
|
|
return 0, errors.New("Not enough data to read uint32")
|
|
}
|
|
|
|
return stream.ReadU32LENext(1)[0], nil
|
|
}
|
|
|
|
// ReadUInt32BE reads a Big-Endian encoded uint32
|
|
func (stream *StreamIn) ReadUInt32BE() (uint32, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 4 {
|
|
return 0, errors.New("Not enough data to read uint32")
|
|
}
|
|
|
|
return stream.ReadU32BENext(1)[0], nil
|
|
}
|
|
|
|
// ReadInt32LE reads a Little-Endian encoded int32
|
|
func (stream *StreamIn) ReadInt32LE() (int32, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 4 {
|
|
return 0, errors.New("Not enough data to read int32")
|
|
}
|
|
|
|
return int32(stream.ReadU32LENext(1)[0]), nil
|
|
}
|
|
|
|
// ReadInt32BE reads a Big-Endian encoded int32
|
|
func (stream *StreamIn) ReadInt32BE() (int32, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 4 {
|
|
return 0, errors.New("Not enough data to read int32")
|
|
}
|
|
|
|
return int32(stream.ReadU32BENext(1)[0]), nil
|
|
}
|
|
|
|
// ReadUInt64LE reads a Little-Endian encoded uint64
|
|
func (stream *StreamIn) ReadUInt64LE() (uint64, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 8 {
|
|
return 0, errors.New("Not enough data to read uint64")
|
|
}
|
|
|
|
return stream.ReadU64LENext(1)[0], nil
|
|
}
|
|
|
|
// ReadUInt64BE reads a Big-Endian encoded uint64
|
|
func (stream *StreamIn) ReadUInt64BE() (uint64, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 8 {
|
|
return 0, errors.New("Not enough data to read uint64")
|
|
}
|
|
|
|
return stream.ReadU64BENext(1)[0], nil
|
|
}
|
|
|
|
// ReadInt64LE reads a Little-Endian encoded int64
|
|
func (stream *StreamIn) ReadInt64LE() (int64, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 8 {
|
|
return 0, errors.New("Not enough data to read int64")
|
|
}
|
|
|
|
return int64(stream.ReadU64LENext(1)[0]), nil
|
|
}
|
|
|
|
// ReadInt64BE reads a Big-Endian encoded int64
|
|
func (stream *StreamIn) ReadInt64BE() (int64, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 8 {
|
|
return 0, errors.New("Not enough data to read int64")
|
|
}
|
|
|
|
return int64(stream.ReadU64BENext(1)[0]), nil
|
|
}
|
|
|
|
// ReadFloat32LE reads a Little-Endian encoded float32
|
|
func (stream *StreamIn) ReadFloat32LE() (float32, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 4 {
|
|
return 0, errors.New("Not enough data to read float32")
|
|
}
|
|
|
|
return stream.ReadF32LENext(1)[0], nil
|
|
}
|
|
|
|
// ReadFloat32BE reads a Big-Endian encoded float32
|
|
func (stream *StreamIn) ReadFloat32BE() (float32, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 4 {
|
|
return 0, errors.New("Not enough data to read float32")
|
|
}
|
|
|
|
return stream.ReadF32BENext(1)[0], nil
|
|
}
|
|
|
|
// ReadFloat64LE reads a Little-Endian encoded float64
|
|
func (stream *StreamIn) ReadFloat64LE() (float64, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 8 {
|
|
return 0, errors.New("Not enough data to read float64")
|
|
}
|
|
|
|
return stream.ReadF64LENext(1)[0], nil
|
|
}
|
|
|
|
// ReadFloat64BE reads a Big-Endian encoded float64
|
|
func (stream *StreamIn) ReadFloat64BE() (float64, error) {
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < 8 {
|
|
return 0, errors.New("Not enough data to read float64")
|
|
}
|
|
|
|
return stream.ReadF64BENext(1)[0], nil
|
|
}
|
|
|
|
// ReadString reads and returns a nex string type
|
|
func (stream *StreamIn) ReadString() (string, error) {
|
|
length, err := stream.ReadUInt16LE()
|
|
if err != nil {
|
|
return "", fmt.Errorf("Failed to read NEX string length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length) {
|
|
return "", errors.New("NEX string length longer than data size")
|
|
}
|
|
|
|
stringData := stream.ReadBytesNext(int64(length))
|
|
str := string(stringData)
|
|
|
|
return strings.TrimRight(str, "\x00"), nil
|
|
}
|
|
|
|
// ReadBuffer reads a nex Buffer type
|
|
func (stream *StreamIn) ReadBuffer() ([]byte, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return []byte{}, fmt.Errorf("Failed to read NEX buffer length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length) {
|
|
return []byte{}, errors.New("NEX buffer length longer than data size")
|
|
}
|
|
|
|
data := stream.ReadBytesNext(int64(length))
|
|
|
|
return data, nil
|
|
}
|
|
|
|
// ReadQBuffer reads a nex qBuffer type
|
|
func (stream *StreamIn) ReadQBuffer() ([]byte, error) {
|
|
length, err := stream.ReadUInt16LE()
|
|
if err != nil {
|
|
return []byte{}, fmt.Errorf("Failed to read NEX qBuffer length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length) {
|
|
return []byte{}, errors.New("NEX qBuffer length longer than data size")
|
|
}
|
|
|
|
data := stream.ReadBytesNext(int64(length))
|
|
|
|
return data, nil
|
|
}
|
|
|
|
// ReadStructure reads a nex Structure type
|
|
func (stream *StreamIn) ReadStructure(structure StructureInterface) (StructureInterface, error) {
|
|
if structure.ParentType() != nil {
|
|
_, err := stream.ReadStructure(structure.ParentType())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read structure parent. %s", err.Error())
|
|
}
|
|
}
|
|
|
|
nexVersion := stream.Server.NEXVersion()
|
|
|
|
if nexVersion.Major >= 3 && nexVersion.Minor >= 5 {
|
|
version, err := stream.ReadUInt8()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read NEX Structure version. %s", err.Error())
|
|
}
|
|
|
|
structureLength, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read NEX Structure content length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(structureLength) {
|
|
return nil, errors.New("NEX Structure content length longer than data size")
|
|
}
|
|
|
|
structure.SetStructureVersion(version)
|
|
}
|
|
|
|
err := structure.ExtractFromStream(stream)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read structure from stream. %s", err.Error())
|
|
}
|
|
|
|
return structure, nil
|
|
}
|
|
|
|
// ReadVariant reads a Variant type. This type can hold 7 different types
|
|
func (stream *StreamIn) ReadVariant() (*Variant, error) {
|
|
variant := NewVariant()
|
|
|
|
err := variant.ExtractFromStream(stream)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read Variant. %s", err.Error())
|
|
}
|
|
|
|
return variant, nil
|
|
}
|
|
|
|
// ReadMap reads a Map type with the given key and value types
|
|
func (stream *StreamIn) ReadMap(keyFunction interface{}, valueFunction interface{}) (map[interface{}]interface{}, error) {
|
|
/*
|
|
TODO: Make this not suck
|
|
|
|
Map types can have any type as the key and any type as the value
|
|
Due to strict typing we cannot just pass stream functions as these values and call them
|
|
At the moment this just reads what type you want from the interface{} function type
|
|
*/
|
|
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read Map length. %s", err.Error())
|
|
}
|
|
|
|
newMap := make(map[interface{}]interface{})
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
var key interface{}
|
|
var value interface{}
|
|
var err error
|
|
|
|
switch keyFunction.(type) {
|
|
case func() (string, error):
|
|
key, err = stream.ReadString()
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read Map key. %s", err.Error())
|
|
}
|
|
|
|
switch valueFunction.(type) {
|
|
case func() *Variant:
|
|
value, err = stream.ReadVariant()
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read Map value. %s", err.Error())
|
|
}
|
|
|
|
newMap[key] = value
|
|
}
|
|
|
|
return newMap, nil
|
|
}
|
|
|
|
// ReadDateTime reads a DateTime type
|
|
func (stream *StreamIn) ReadDateTime() (*DateTime, error) {
|
|
value, err := stream.ReadUInt64LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read DateTime value. %s", err.Error())
|
|
}
|
|
|
|
return NewDateTime(value), nil
|
|
}
|
|
|
|
// ReadDataHolder reads a DataHolder type
|
|
func (stream *StreamIn) ReadDataHolder() (*DataHolder, error) {
|
|
dataHolder := NewDataHolder()
|
|
err := dataHolder.ExtractFromStream(stream)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read DateHolder. %s", err.Error())
|
|
}
|
|
|
|
return dataHolder, nil
|
|
}
|
|
|
|
// ReadStationURL reads a StationURL type
|
|
func (stream *StreamIn) ReadStationURL() (*StationURL, error) {
|
|
stationString, err := stream.ReadString()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read StationURL. %s", err.Error())
|
|
}
|
|
|
|
return NewStationURL(stationString), nil
|
|
}
|
|
|
|
// ReadListUInt8 reads a list of uint8 types
|
|
func (stream *StreamIn) ReadListUInt8() ([]uint8, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint8> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length) {
|
|
return nil, errors.New("NEX List<uint8> length longer than data size")
|
|
}
|
|
|
|
list := make([]uint8, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadUInt8()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint8> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListInt8 reads a list of int8 types
|
|
func (stream *StreamIn) ReadListInt8() ([]int8, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int8> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length) {
|
|
return nil, errors.New("NEX List<int8> length longer than data size")
|
|
}
|
|
|
|
list := make([]int8, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadInt8()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int8> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListUInt16LE reads a list of Little-Endian encoded uint16 types
|
|
func (stream *StreamIn) ReadListUInt16LE() ([]uint16, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint16> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*2) {
|
|
return nil, errors.New("NEX List<uint16> length longer than data size")
|
|
}
|
|
|
|
list := make([]uint16, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadUInt16LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint16> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListUInt16BE reads a list of Big-Endian encoded uint16 types
|
|
func (stream *StreamIn) ReadListUInt16BE() ([]uint16, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint16> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*2) {
|
|
return nil, errors.New("NEX List<uint16> length longer than data size")
|
|
}
|
|
|
|
list := make([]uint16, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadUInt16BE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint16> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListInt16LE reads a list of Little-Endian encoded int16 types
|
|
func (stream *StreamIn) ReadListInt16LE() ([]int16, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int16> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*2) {
|
|
return nil, errors.New("NEX List<int16> length longer than data size")
|
|
}
|
|
|
|
list := make([]int16, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadInt16LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int16> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListInt16BE reads a list of Big-Endian encoded uint16 types
|
|
func (stream *StreamIn) ReadListInt16BE() ([]int16, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int16> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*2) {
|
|
return nil, errors.New("NEX List<int16> length longer than data size")
|
|
}
|
|
|
|
list := make([]int16, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadInt16BE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int16> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListUInt32LE reads a list of Little-Endian encoded uint32 types
|
|
func (stream *StreamIn) ReadListUInt32LE() ([]uint32, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint32> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*4) {
|
|
return nil, errors.New("NEX List<uint32> length longer than data size")
|
|
}
|
|
|
|
list := make([]uint32, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint32> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListUInt32BE reads a list of Big-Endian encoded uint32 types
|
|
func (stream *StreamIn) ReadListUInt32BE() ([]uint32, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint32> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*4) {
|
|
return nil, errors.New("NEX List<uint32> length longer than data size")
|
|
}
|
|
|
|
list := make([]uint32, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadUInt32BE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint32> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListInt32LE reads a list of Little-Endian encoded int32 types
|
|
func (stream *StreamIn) ReadListInt32LE() ([]int32, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int32> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*4) {
|
|
return nil, errors.New("NEX List<int32> length longer than data size")
|
|
}
|
|
|
|
list := make([]int32, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int32> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListInt32BE reads a list of Big-Endian encoded int32 types
|
|
func (stream *StreamIn) ReadListInt32BE() ([]int32, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int32> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*4) {
|
|
return nil, errors.New("NEX List<int32> length longer than data size")
|
|
}
|
|
|
|
list := make([]int32, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadInt32BE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int32> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListUInt64LE reads a list of Little-Endian encoded uint64 types
|
|
func (stream *StreamIn) ReadListUInt64LE() ([]uint64, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint64> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*8) {
|
|
return nil, errors.New("NEX List<uint64> length longer than data size")
|
|
}
|
|
|
|
list := make([]uint64, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadUInt64LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint64> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListUInt64BE reads a list of Big-Endian encoded uint64 types
|
|
func (stream *StreamIn) ReadListUInt64BE() ([]uint64, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint64> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*8) {
|
|
return nil, errors.New("NEX List<uint64> length longer than data size")
|
|
}
|
|
|
|
list := make([]uint64, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadUInt64BE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<uint64> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListInt64LE reads a list of Little-Endian encoded int64 types
|
|
func (stream *StreamIn) ReadListInt64LE() ([]int64, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int64> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*8) {
|
|
return nil, errors.New("NEX List<int64> length longer than data size")
|
|
}
|
|
|
|
list := make([]int64, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadInt64LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int64> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListInt64BE reads a list of Big-Endian encoded int64 types
|
|
func (stream *StreamIn) ReadListInt64BE() ([]int64, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int64> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*8) {
|
|
return nil, errors.New("NEX List<int64> length longer than data size")
|
|
}
|
|
|
|
list := make([]int64, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadInt64BE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<int64> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListFloat32LE reads a list of Little-Endian encoded float32 types
|
|
func (stream *StreamIn) ReadListFloat32LE() ([]float32, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<float32> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*4) {
|
|
return nil, errors.New("NEX List<float32> length longer than data size")
|
|
}
|
|
|
|
list := make([]float32, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadFloat32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<float32> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListFloat32BE reads a list of Big-Endian encoded float32 types
|
|
func (stream *StreamIn) ReadListFloat32BE() ([]float32, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<float32> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*4) {
|
|
return nil, errors.New("NEX List<float32> length longer than data size")
|
|
}
|
|
|
|
list := make([]float32, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadFloat32BE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<float32> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListFloat64LE reads a list of Little-Endian encoded float64 types
|
|
func (stream *StreamIn) ReadListFloat64LE() ([]float64, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<float64> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*4) {
|
|
return nil, errors.New("NEX List<float64> length longer than data size")
|
|
}
|
|
|
|
list := make([]float64, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadFloat64LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<float64> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListFloat64BE reads a list of Big-Endian encoded float64 types
|
|
func (stream *StreamIn) ReadListFloat64BE() ([]float64, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<float64> length. %s", err.Error())
|
|
}
|
|
|
|
if len(stream.Bytes()[stream.ByteOffset():]) < int(length*4) {
|
|
return nil, errors.New("NEX List<float64> length longer than data size")
|
|
}
|
|
|
|
list := make([]float64, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadFloat64BE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<float64> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListString reads a list of NEX String types
|
|
func (stream *StreamIn) ReadListString() ([]string, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<String> length. %s", err.Error())
|
|
}
|
|
|
|
list := make([]string, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadString()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<String> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListBuffer reads a list of NEX Buffer types
|
|
func (stream *StreamIn) ReadListBuffer() ([][]byte, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<Buffer> length. %s", err.Error())
|
|
}
|
|
|
|
list := make([][]byte, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadBuffer()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<Buffer> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListQBuffer reads a list of NEX qBuffer types
|
|
func (stream *StreamIn) ReadListQBuffer() ([][]byte, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<qBuffer> length. %s", err.Error())
|
|
}
|
|
|
|
list := make([][]byte, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadQBuffer()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<qBuffer> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListStationURL reads a list of NEX Station URL types
|
|
func (stream *StreamIn) ReadListStationURL() ([]*StationURL, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<StationURL> length. %s", err.Error())
|
|
}
|
|
|
|
list := make([]*StationURL, 0, length)
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
value, err := stream.ReadStationURL()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<StationURL> value at index %d. %s", i, err.Error())
|
|
}
|
|
|
|
list = append(list, value)
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// ReadListStructure reads and returns a list structure types
|
|
func (stream *StreamIn) ReadListStructure(structure StructureInterface) (interface{}, error) {
|
|
length, err := stream.ReadUInt32LE()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to read List<Structure> length. %s", err.Error())
|
|
}
|
|
|
|
structureType := reflect.TypeOf(structure)
|
|
structureSlice := reflect.MakeSlice(reflect.SliceOf(structureType), 0, int(length))
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
newStructure := structure.Copy()
|
|
|
|
extractedStructure, err := stream.ReadStructure(newStructure)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
structureSlice = reflect.Append(structureSlice, reflect.ValueOf(extractedStructure))
|
|
}
|
|
|
|
return structureSlice.Interface(), nil
|
|
}
|
|
|
|
// NewStreamIn returns a new NEX input stream
|
|
func NewStreamIn(data []byte, server *Server) *StreamIn {
|
|
return &StreamIn{
|
|
Buffer: crunch.NewBuffer(data),
|
|
Server: server,
|
|
}
|
|
}
|