Add fuzz testing for Section encoding/decoding with multiple edge cases
This commit is contained in:
+21
-42
@@ -1,54 +1,33 @@
|
|||||||
package level
|
package level
|
||||||
|
|
||||||
import (
|
import "io"
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/admin-else/strom/data"
|
type Chunk struct {
|
||||||
"github.com/admin-else/strom/util"
|
Sections []Section
|
||||||
)
|
version string
|
||||||
|
|
||||||
type BlockState struct {
|
|
||||||
Id string
|
|
||||||
Properties map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
func ReadChunkFromChunkPacketData(r io.Reader, version string, worldHeight int) (err error) {
|
||||||
ChunkWidth = 16
|
c := &Chunk{}
|
||||||
ChunkColumns = ChunkWidth * ChunkWidth
|
c.version = version
|
||||||
BlocksPerChunkSection = ChunkWidth * ChunkWidth * ChunkWidth
|
nSections := worldHeight / ChunkWidth
|
||||||
ChunkBiomesWidth = 4
|
|
||||||
BiomesPerChunkSection = ChunkBiomesWidth * ChunkBiomesWidth * ChunkBiomesWidth
|
|
||||||
)
|
|
||||||
|
|
||||||
type Section struct {
|
c.Sections = make([]Section, nSections)
|
||||||
Blocks *Storage[*BlockState]
|
for i := range c.Sections {
|
||||||
Biomes *Storage[string]
|
c.Sections[i], err = SectionDecodePacket(r, version)
|
||||||
}
|
if err != nil {
|
||||||
|
return
|
||||||
func PossibleBpesBlocks(version string) (ret []uint8) {
|
}
|
||||||
maxBpe := util.BpeByNum(float64(len(data.BlocksForVersion(version))))
|
}
|
||||||
ret = []uint8{0, 4, 5, 6, 7, 8, maxBpe}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func PossibleBpesBiomes(version string) (ret []uint8) {
|
|
||||||
maxBpe := uint8(math.Ceil(math.Log2(float64(len(data.BiomesForVersion(version))))))
|
|
||||||
ret = []uint8{0, 1, 2, 3, maxBpe}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SectionFromPacket(r io.Reader, version string) (s *Section, err error) {
|
|
||||||
s = &Section{}
|
|
||||||
s.Blocks = NewStorage[*BlockState](BlocksPerChunkSection, PossibleBpesBlocks(version))
|
|
||||||
s.Biomes = NewStorage[string](BiomesPerChunkSection, PossibleBpesBiomes(version))
|
|
||||||
|
|
||||||
var bitsPerEntryBlocks uint8
|
func (c *Chunk) WriteChunkData(w io.Writer) (err error) {
|
||||||
err = binary.Read(r, binary.BigEndian, &bitsPerEntryBlocks)
|
for _, s := range c.Sections {
|
||||||
if err != nil {
|
err = SectionEncodePacket(w, s)
|
||||||
return
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
package level
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"github.com/admin-else/strom/data"
|
||||||
|
"github.com/admin-else/strom/proto_base"
|
||||||
|
"github.com/admin-else/strom/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BlockState struct {
|
||||||
|
Id string
|
||||||
|
Properties map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ChunkWidth = 16
|
||||||
|
ChunkColumns = ChunkWidth * ChunkWidth
|
||||||
|
BlocksPerChunkSection = ChunkWidth * ChunkWidth * ChunkWidth
|
||||||
|
ChunkBiomesWidth = 4
|
||||||
|
BiomesPerChunkSection = ChunkBiomesWidth * ChunkBiomesWidth * ChunkBiomesWidth
|
||||||
|
)
|
||||||
|
|
||||||
|
type Section struct {
|
||||||
|
BlockCount int16
|
||||||
|
Blocks, Biomes *Storage
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeBiomeFormat(version string) StorageFormat {
|
||||||
|
directBpe := uint8(math.Ceil(math.Log2(float64(len(data.BiomesForVersion(version))))))
|
||||||
|
return StorageFormat{
|
||||||
|
AvailableBpes: []uint8{0, 1, 2, 3, directBpe},
|
||||||
|
BiggestDirect: true,
|
||||||
|
Len: BiomesPerChunkSection,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeBlockFormat(version string) StorageFormat {
|
||||||
|
directBpe := uint8(math.Ceil(math.Log2(float64(len(data.BlocksForVersion(version))))))
|
||||||
|
return StorageFormat{
|
||||||
|
AvailableBpes: []uint8{0, 1, 2, 3, directBpe},
|
||||||
|
BiggestDirect: true,
|
||||||
|
Len: BiomesPerChunkSection,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var BadPaletteLenErr = errors.New("bad palette length")
|
||||||
|
|
||||||
|
func ReadSectionStorage(r io.Reader, format StorageFormat) (s *Storage, err error) {
|
||||||
|
var bpe uint8
|
||||||
|
err = binary.Read(r, binary.BigEndian, &bpe)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var pallette []int32
|
||||||
|
if bpe == 0 {
|
||||||
|
var v int32
|
||||||
|
v, err = proto_base.DecodeVarInt(r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pallette = []int32{v}
|
||||||
|
} else if !util.IsLastElement(format.AvailableBpes, bpe) {
|
||||||
|
var paletteLen int32
|
||||||
|
paletteLen, err = proto_base.DecodeVarInt(r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if paletteLen < 0 {
|
||||||
|
err = BadPaletteLenErr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for range pallette {
|
||||||
|
var v int32
|
||||||
|
v, err = proto_base.DecodeVarInt(r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pallette = append(pallette, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return format.ImportFromReader(r, bpe, pallette)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteSectionStorage(w io.Writer, s *Storage) (err error) {
|
||||||
|
err = binary.Write(w, binary.BigEndian, s.bpe)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if s.bpe == 0 {
|
||||||
|
err = proto_base.EncodeVarInt(w, s.palette[0])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if !util.IsLastElement(s.format.AvailableBpes, s.bpe) {
|
||||||
|
err = proto_base.EncodeVarInt(w, int32(len(s.palette)))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v := range s.palette {
|
||||||
|
err = proto_base.EncodeVarInt(w, v)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return binary.Write(w, binary.BigEndian, s.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SectionDecodePacket(r io.Reader, version string) (s Section, err error) {
|
||||||
|
s = Section{}
|
||||||
|
err = binary.Read(r, binary.BigEndian, &s.BlockCount)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.Blocks, err = ReadSectionStorage(r, MakeBlockFormat(version))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.Biomes, err = ReadSectionStorage(r, MakeBiomeFormat(version))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SectionEncodePacket(w io.Writer, s Section) (err error) {
|
||||||
|
err = binary.Write(w, binary.BigEndian, s.BlockCount)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = WriteSectionStorage(w, s.Blocks)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = WriteSectionStorage(w, s.Biomes)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package level_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/admin-else/strom/level"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FuzzSectionDeEnCodePacket(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, raw []byte) {
|
||||||
|
r := bytes.NewReader(raw)
|
||||||
|
s1, err := level.SectionDecodePacket(r, TestVersion)
|
||||||
|
if err != nil {
|
||||||
|
t.Skipf("decode failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
err = level.SectionEncodePacket(buf, s1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s2, err := level.SectionDecodePacket(buf, TestVersion)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if s1.BlockCount != s2.BlockCount {
|
||||||
|
t.Error("BlockCount mismatch")
|
||||||
|
}
|
||||||
|
if level.CompareStorage(s1.Blocks, s2.Blocks) {
|
||||||
|
t.Error("Blocks mismatch")
|
||||||
|
}
|
||||||
|
if level.CompareStorage(s1.Biomes, s2.Biomes) {
|
||||||
|
t.Error("Biomes mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
package level
|
package level
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"slices"
|
"slices"
|
||||||
)
|
)
|
||||||
@@ -53,6 +55,28 @@ func (r StorageFormat) ImportDataDirect(data []uint64) (s *Storage, err error) {
|
|||||||
return r.Import(data, r.AvailableBpes[0], nil)
|
return r.Import(data, r.AvailableBpes[0], nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r StorageFormat) ImportFromReader(reader io.Reader, bpe uint8, palette []int32) (s *Storage, err error) {
|
||||||
|
if !slices.Contains(r.AvailableBpes, bpe) {
|
||||||
|
err = BpeNotAvailableErr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var longs []uint64
|
||||||
|
if bpe == 0 {
|
||||||
|
return r.Import(longs, bpe, palette)
|
||||||
|
}
|
||||||
|
elementsPerLong := int32(64 / int(bpe))
|
||||||
|
numberOfLongs := int(math.Ceil(float64(r.Len) / float64(elementsPerLong)))
|
||||||
|
for range numberOfLongs {
|
||||||
|
var long uint64
|
||||||
|
err = binary.Read(reader, binary.BigEndian, &long) // surely this works?
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
longs = append(longs, long)
|
||||||
|
}
|
||||||
|
return r.Import(longs, bpe, palette)
|
||||||
|
}
|
||||||
|
|
||||||
type Storage struct {
|
type Storage struct {
|
||||||
format StorageFormat
|
format StorageFormat
|
||||||
data []uint64
|
data []uint64
|
||||||
@@ -81,14 +105,14 @@ func (r *Storage) resize(bpe uint8) {
|
|||||||
r.maxAtCurrentBpe = 1
|
r.maxAtCurrentBpe = 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
numberOfElements := int32(64 / int(bpe))
|
elementsPerLong := int32(64 / int(bpe))
|
||||||
numberOfLongs := int(math.Ceil(float64(r.format.Len) / float64(numberOfElements)))
|
numberOfLongs := int(math.Ceil(float64(r.format.Len) / float64(elementsPerLong)))
|
||||||
newData := make([]uint64, numberOfLongs)
|
newData := make([]uint64, numberOfLongs)
|
||||||
mask := (uint64(1) << uint32(bpe)) - 1
|
mask := (uint64(1) << uint32(bpe)) - 1
|
||||||
maxAtCurrentBpe := int32(1 << bpe)
|
maxAtCurrentBpe := int32(1 << bpe)
|
||||||
if r.bpe == 0 {
|
if r.bpe == 0 {
|
||||||
r.bpe = bpe
|
r.bpe = bpe
|
||||||
r.elementsPerLong = numberOfElements
|
r.elementsPerLong = elementsPerLong
|
||||||
r.data = newData
|
r.data = newData
|
||||||
r.mask = mask
|
r.mask = mask
|
||||||
r.maxAtCurrentBpe = maxAtCurrentBpe
|
r.maxAtCurrentBpe = maxAtCurrentBpe
|
||||||
@@ -102,13 +126,13 @@ func (r *Storage) resize(bpe uint8) {
|
|||||||
} else {
|
} else {
|
||||||
v = int32((r.data[i/r.elementsPerLong] >> ((i % r.elementsPerLong) * int32(r.bpe))) & r.mask)
|
v = int32((r.data[i/r.elementsPerLong] >> ((i % r.elementsPerLong) * int32(r.bpe))) & r.mask)
|
||||||
}
|
}
|
||||||
newData[i/int32(numberOfElements)] |= uint64(v) << ((i % int32(numberOfElements)) * int32(bpe))
|
newData[i/int32(elementsPerLong)] |= uint64(v) << ((i % int32(elementsPerLong)) * int32(bpe))
|
||||||
}
|
}
|
||||||
if resizeDirect {
|
if resizeDirect {
|
||||||
r.palette = nil
|
r.palette = nil
|
||||||
}
|
}
|
||||||
r.bpe = bpe
|
r.bpe = bpe
|
||||||
r.elementsPerLong = numberOfElements
|
r.elementsPerLong = elementsPerLong
|
||||||
r.data = newData
|
r.data = newData
|
||||||
r.mask = mask
|
r.mask = mask
|
||||||
r.maxAtCurrentBpe = maxAtCurrentBpe
|
r.maxAtCurrentBpe = maxAtCurrentBpe
|
||||||
@@ -196,3 +220,21 @@ func (r *Storage) appendPalette(v int32) (i int, err error) {
|
|||||||
i = len(r.palette) - 1
|
i = len(r.palette) - 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Storage) Export() (data []uint64, bpe uint8, palette []int32, format StorageFormat) {
|
||||||
|
return r.data, r.bpe, r.palette, r.format
|
||||||
|
}
|
||||||
|
|
||||||
|
func CompareStorage(a, b *Storage) bool {
|
||||||
|
if a.format.Len != b.format.Len {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range a.format.Len {
|
||||||
|
av, _ := a.Get(i)
|
||||||
|
bv, _ := b.Get(i)
|
||||||
|
if av == bv {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
[]byte("000\xcf\xff\xff\xe88")
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
[]byte("00A\x00")
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
[]byte("00\x000")
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package mapstructure
|
||||||
|
|
||||||
|
var DefaultFormat = NewFormat("mapstructure", WithRequireAll(), WithTrySnakeCase(), WithTryLowCase())
|
||||||
|
|
||||||
|
func Decode(data any, v any) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/admin-else/strom/data"
|
"github.com/admin-else/strom/data"
|
||||||
|
"github.com/admin-else/strom/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ToDoError = errors.New("to do")
|
var ToDoError = errors.New("to do")
|
||||||
@@ -126,11 +127,11 @@ func (g *Generator) VisitNameAndData(tName string, tData any) (e ast.Expr, err e
|
|||||||
}
|
}
|
||||||
t, found := g.Protocol.Types.Types[tName]
|
t, found := g.Protocol.Types.Types[tName]
|
||||||
if t != "native" && found {
|
if t != "native" && found {
|
||||||
return Ident(CamelCase(tName)), nil
|
return Ident(util.CamelCase(tName)), nil
|
||||||
}
|
}
|
||||||
t, found = g.CurrentlyGeneratingTypes.Types[tName]
|
t, found = g.CurrentlyGeneratingTypes.Types[tName]
|
||||||
if found {
|
if found {
|
||||||
return Ident(g.CurrentlyGeneratingTypesPrefix + CamelCase(tName)), nil
|
return Ident(g.CurrentlyGeneratingTypesPrefix + util.CamelCase(tName)), nil
|
||||||
}
|
}
|
||||||
err = fmt.Errorf("unknown type %s", tName)
|
err = fmt.Errorf("unknown type %s", tName)
|
||||||
return
|
return
|
||||||
@@ -212,7 +213,7 @@ func (g *Generator) GenerateTypes(prefix string, types Types) (err error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
tName := prefix + CamelCase(k)
|
tName := prefix + util.CamelCase(k)
|
||||||
g.CurrentlyGeneratingTypeName = tName
|
g.CurrentlyGeneratingTypeName = tName
|
||||||
|
|
||||||
e, retExpr := FixPointerReceivers(e)
|
e, retExpr := FixPointerReceivers(e)
|
||||||
@@ -293,7 +294,7 @@ func (g *Generator) GenerateProtocol(protocol Protocol, version string) (err err
|
|||||||
v := typeData.([]any)[1].([]any)[1].(map[string]any)["type"].([]any)[1].(map[string]any)["fields"].(map[string]any)
|
v := typeData.([]any)[1].([]any)[1].(map[string]any)["type"].([]any)[1].(map[string]any)["fields"].(map[string]any)
|
||||||
for _, k2 := range OrderedKeys(v) {
|
for _, k2 := range OrderedKeys(v) {
|
||||||
v2 := v[k2].(string)
|
v2 := v[k2].(string)
|
||||||
typeName := prefix + CamelCase(v2)
|
typeName := prefix + util.CamelCase(v2)
|
||||||
g.packetInfos = append(g.packetInfos, PacketInfo{
|
g.packetInfos = append(g.packetInfos, PacketInfo{
|
||||||
PacketDef: v2,
|
PacketDef: v2,
|
||||||
TName: typeName,
|
TName: typeName,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/admin-else/strom/proto_generator/protodef"
|
"github.com/admin-else/strom/proto_generator/protodef"
|
||||||
|
"github.com/admin-else/strom/util"
|
||||||
"github.com/go-viper/mapstructure/v2"
|
"github.com/go-viper/mapstructure/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ func ContainerCompareTo(g *Generator, parts []string, inExpr ast.Expr, dataRaw a
|
|||||||
}
|
}
|
||||||
for _, field := range data {
|
for _, field := range data {
|
||||||
if field.Name == name {
|
if field.Name == name {
|
||||||
return g.VisitCompareTo(parts, SelectorExprAndStr(inExpr, CamelCase(field.Name)), field.Type)
|
return g.VisitCompareTo(parts, SelectorExprAndStr(inExpr, util.CamelCase(field.Name)), field.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = errors.New("field not found")
|
err = errors.New("field not found")
|
||||||
@@ -87,7 +88,7 @@ func BitfieldCompareTo(_ *Generator, parts []string, inExpr ast.Expr, dataRaw an
|
|||||||
cet = CaseExprTypeOnlyNumber
|
cet = CaseExprTypeOnlyNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
e = SelectorExprAndStr(inExpr, CamelCase(fieldName))
|
e = SelectorExprAndStr(inExpr, util.CamelCase(fieldName))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/admin-else/strom/proto_generator/protodef"
|
"github.com/admin-else/strom/proto_generator/protodef"
|
||||||
|
"github.com/admin-else/strom/util"
|
||||||
"github.com/go-viper/mapstructure/v2"
|
"github.com/go-viper/mapstructure/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ func ContainerDecoder(g *Generator, varToSet ast.Expr, dataRaw any, name string)
|
|||||||
|
|
||||||
for _, field := range data {
|
for _, field := range data {
|
||||||
var statements []ast.Stmt
|
var statements []ast.Stmt
|
||||||
cName := CamelCase(field.Name)
|
cName := util.CamelCase(field.Name)
|
||||||
if field.Anon {
|
if field.Anon {
|
||||||
cName = "Anon"
|
cName = "Anon"
|
||||||
}
|
}
|
||||||
@@ -106,7 +107,7 @@ func OptionDecoder(g *Generator, varToSet ast.Expr, dataRaw any, name string) (s
|
|||||||
|
|
||||||
func ArrayDecoder(g *Generator, varToSet ast.Expr, dataRaw any, name string) (s []ast.Stmt, err error) {
|
func ArrayDecoder(g *Generator, varToSet ast.Expr, dataRaw any, name string) (s []ast.Stmt, err error) {
|
||||||
var data protodef.Array
|
var data protodef.Array
|
||||||
lName := "l" + CamelCase(name)
|
lName := "l" + util.CamelCase(name)
|
||||||
err = mapstructure.Decode(dataRaw, &data)
|
err = mapstructure.Decode(dataRaw, &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -259,7 +260,7 @@ func SwitchDecoder(g *Generator, varToSet ast.Expr, dataRaw any, name string) (s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tName := name + CamelCase(fName) + "Tmp"
|
tName := name + util.CamelCase(fName) + "Tmp"
|
||||||
s1 := VarStmt(tName, tType)
|
s1 := VarStmt(tName, tType)
|
||||||
s3 := Assign121(varToSet, Ident(tName))
|
s3 := Assign121(varToSet, Ident(tName))
|
||||||
var caseDecodeValueStmts []ast.Stmt
|
var caseDecodeValueStmts []ast.Stmt
|
||||||
@@ -309,7 +310,7 @@ func MapperDecoder(g *Generator, varToSet ast.Expr, dataRaw any, name string) (s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
kName := CamelCase(name) + "Key"
|
kName := util.CamelCase(name) + "Key"
|
||||||
kType, err := g.VisitType(data.Type)
|
kType, err := g.VisitType(data.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -346,7 +347,7 @@ func BufferDecoder(g *Generator, varToSet ast.Expr, dataRaw any, name string) (s
|
|||||||
// rawString, err := io.ReadAll(io.LimitReader(r, int64(l)))
|
// rawString, err := io.ReadAll(io.LimitReader(r, int64(l)))
|
||||||
|
|
||||||
if data.CountType != nil {
|
if data.CountType != nil {
|
||||||
lName := "l" + CamelCase(name)
|
lName := "l" + util.CamelCase(name)
|
||||||
var countType ast.Expr
|
var countType ast.Expr
|
||||||
countType, err = g.VisitType(data.CountType)
|
countType, err = g.VisitType(data.CountType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -411,7 +412,7 @@ func BitFieldDecoder(g *Generator, varToSet ast.Expr, dataRaw any, name string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rShiftBy := totalSize - field.Size
|
rShiftBy := totalSize - field.Size
|
||||||
fieldToSet := SelectorExprAndStr(varToSet, CamelCase(field.Name))
|
fieldToSet := SelectorExprAndStr(varToSet, util.CamelCase(field.Name))
|
||||||
|
|
||||||
var getDataExpr ast.Expr
|
var getDataExpr ast.Expr
|
||||||
getDataExpr = RightShift(
|
getDataExpr = RightShift(
|
||||||
@@ -470,7 +471,7 @@ func RegistryEntryHolderSetDecoder(g *Generator, varToSet ast.Expr, dataRaw any,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
lName := "l" + CamelCase(name)
|
lName := "l" + util.CamelCase(name)
|
||||||
s1 := VarStmt(lName, countType)
|
s1 := VarStmt(lName, countType)
|
||||||
s2, err := g.VisitDecoder(Ident(lName), "varint", name)
|
s2, err := g.VisitDecoder(Ident(lName), "varint", name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/admin-else/strom/proto_generator/protodef"
|
"github.com/admin-else/strom/proto_generator/protodef"
|
||||||
|
"github.com/admin-else/strom/util"
|
||||||
"github.com/go-viper/mapstructure/v2"
|
"github.com/go-viper/mapstructure/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,11 +38,11 @@ func ContainerEncoder(g *Generator, varToSet ast.Expr, dataRaw any, name string)
|
|||||||
|
|
||||||
for _, field := range data {
|
for _, field := range data {
|
||||||
var statements []ast.Stmt
|
var statements []ast.Stmt
|
||||||
cName := CamelCase(field.Name)
|
cName := util.CamelCase(field.Name)
|
||||||
if field.Anon {
|
if field.Anon {
|
||||||
cName = "Anon"
|
cName = "Anon"
|
||||||
}
|
}
|
||||||
statements, err = g.VisitEncoder(SelectorExprAndStr(varToSet, cName), field.Type, name+CamelCase(cName))
|
statements, err = g.VisitEncoder(SelectorExprAndStr(varToSet, cName), field.Type, name+util.CamelCase(cName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -170,7 +171,7 @@ func BitFieldEncoder(g *Generator, varToSet ast.Expr, dataRaw any, name string)
|
|||||||
Ident(boolFix),
|
Ident(boolFix),
|
||||||
SelectorExprAndStr(
|
SelectorExprAndStr(
|
||||||
varToSet,
|
varToSet,
|
||||||
CamelCase(field.Name),
|
util.CamelCase(field.Name),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
NumLitHex((1<<field.Size)-1),
|
NumLitHex((1<<field.Size)-1),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"go/ast"
|
"go/ast"
|
||||||
|
|
||||||
"github.com/admin-else/strom/proto_generator/protodef"
|
"github.com/admin-else/strom/proto_generator/protodef"
|
||||||
|
"github.com/admin-else/strom/util"
|
||||||
"github.com/go-viper/mapstructure/v2"
|
"github.com/go-viper/mapstructure/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ func VisitContainerType(g *Generator, dataRaw any) (ast.Expr, error) {
|
|||||||
if field.Anon {
|
if field.Anon {
|
||||||
field.Name = "Anon" // lol
|
field.Name = "Anon" // lol
|
||||||
}
|
}
|
||||||
AddFieldToStruct(s, CamelCase(field.Name), t)
|
AddFieldToStruct(s, util.CamelCase(field.Name), t)
|
||||||
}
|
}
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
@@ -137,7 +138,7 @@ func VisitBitFieldType(g *Generator, dataRaw any) (e ast.Expr, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
AddFieldToStruct(ret, CamelCase(field.Name), fieldType)
|
AddFieldToStruct(ret, util.CamelCase(field.Name), fieldType)
|
||||||
}
|
}
|
||||||
e = ret
|
e = ret
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -81,3 +81,7 @@ func SliceRange[T Numeric](s, e T) (ret []T) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsLastElement[T comparable](s []T, e T) bool {
|
||||||
|
return len(s) > 0 && s[len(s)-1] == e
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user