2026-04-06 00:20:51 -05:00

220 lines
3.5 KiB
Go

package main
import (
"bytes"
"encoding/binary"
"errors"
"strings"
)
type Packer struct {
buffer []byte
}
func CreatePacker(buffer []byte) *Packer {
return &Packer{
buffer: buffer,
}
}
func (p *Packer) Size() uint {
return uint(len(p.buffer))
}
func (p *Packer) CheckPacker(types []string) bool {
packerSize := p.Size()
for _, t := range types {
switch t {
case "byte":
if packerSize < 1 {
return false
}
packerSize -= 1
case "word":
if packerSize < 2 {
return false
}
packerSize -= 2
case "int":
if packerSize < 4 {
return false
}
packerSize -= 4
case "long":
if packerSize < 8 {
return false
}
packerSize -= 8
case "array":
if packerSize < 4 {
return false
}
index := p.Size() - packerSize
value := make([]byte, 4)
copy(value, p.buffer[index:index+4])
length := uint(binary.BigEndian.Uint32(value))
packerSize -= 4
if packerSize < length {
return false
}
packerSize -= length
}
}
return true
}
func (p *Packer) ParseInt8() uint8 {
var value = make([]byte, 1)
if p.Size() >= 1 {
if p.Size() == 1 {
copy(value, p.buffer[:p.Size()])
p.buffer = []byte{}
} else {
copy(value, p.buffer[:1])
p.buffer = p.buffer[1:]
}
} else {
return 0
}
return value[0]
}
func (p *Packer) ParseInt16() uint16 {
var value = make([]byte, 2)
if p.Size() >= 2 {
if p.Size() == 2 {
copy(value, p.buffer[:p.Size()])
p.buffer = []byte{}
} else {
copy(value, p.buffer[:2])
p.buffer = p.buffer[2:]
}
} else {
return 0
}
return binary.BigEndian.Uint16(value)
}
func (p *Packer) ParseInt32() uint {
var value = make([]byte, 4)
if p.Size() >= 4 {
if p.Size() == 4 {
copy(value, p.buffer[:p.Size()])
p.buffer = []byte{}
} else {
copy(value, p.buffer[:4])
p.buffer = p.buffer[4:]
}
} else {
return 0
}
return uint(binary.BigEndian.Uint32(value))
}
func (p *Packer) ParseInt64() uint64 {
var value = make([]byte, 8)
if p.Size() >= 8 {
if p.Size() == 8 {
copy(value, p.buffer[:p.Size()])
p.buffer = []byte{}
} else {
copy(value, p.buffer[:8])
p.buffer = p.buffer[8:]
}
} else {
return 0
}
return binary.BigEndian.Uint64(value)
}
func (p *Packer) ParseBytes() []byte {
size := p.ParseInt32()
if p.Size() < size {
return make([]byte, 0)
}
b := p.buffer[:size]
p.buffer = p.buffer[size:]
return b
}
func (p *Packer) ParseString() string {
size := p.ParseInt32()
if p.Size() < size {
return ""
}
b := p.buffer[:size]
p.buffer = p.buffer[size:]
return string(bytes.Trim(b, "\x00"))
}
func PackArray(array []interface{}) ([]byte, error) {
var packData []byte
for i := range array {
switch array[i].(type) {
case []byte:
val := array[i].([]byte)
packData = append(packData, val...)
break
case string:
size := make([]byte, 4)
val := array[i].(string)
if len(val) != 0 {
if !strings.HasSuffix(val, "\x00") {
val += "\x00"
}
}
binary.LittleEndian.PutUint32(size, uint32(len(val)))
packData = append(packData, size...)
packData = append(packData, []byte(val)...)
break
case int:
num := make([]byte, 4)
val := array[i].(int)
binary.LittleEndian.PutUint32(num, uint32(val))
packData = append(packData, num...)
break
case bool:
b := array[i].(bool)
var bt = make([]byte, 1)
bt[0] = 0
if b {
bt[0] = 1
}
packData = append(packData, bt...)
break
default:
return nil, errors.New("PackArray unknown type")
}
}
return packData, nil
}