Skip to content

Commit 619484f

Browse files
authored
Merge pull request #17 from ethanmoffat/fix_gen
Fix generated code: bug discovery from eolib-dotnet implementation
2 parents 5d021aa + 5e68213 commit 619484f

File tree

14 files changed

+5186
-369
lines changed

14 files changed

+5186
-369
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Core library for writing Endless Online applications using the Go programming la
99
The library may be referenced in a project via go get:
1010

1111
```
12-
go get github.com/ethanmoffat/eolib-go@v2.0.1
12+
go get github.com/ethanmoffat/eolib-go@v2.1.0
1313
```
1414

1515
### Sample code

internal/codegen/shared.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func snakeCaseToCamelCase(input string) string {
9999
if ndx != 0 {
100100
tmp = tmp + string(unicode.ToUpper(rune(out[ndx+1])))
101101
} else {
102-
tmp = tmp + string(out[ndx+1])
102+
tmp = tmp + string(unicode.ToLower(rune(out[ndx+1])))
103103
}
104104
}
105105

internal/codegen/struct.go

Lines changed: 154 additions & 44 deletions
Large diffs are not rendered by default.

internal/codegen/types/typesize.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,25 @@ func CalculateTypeSize(typeName string, fullSpec xml.Protocol) (res int, err err
4141
return getPrimitiveTypeSize(typeName, fullSpec)
4242
}
4343

44-
var flattenedInstList []xml.ProtocolInstruction
45-
for _, instruction := range (*structInfo).Instructions {
46-
if instruction.XMLName.Local == "chunked" {
47-
flattenedInstList = append(flattenedInstList, instruction.Chunked...)
48-
} else {
49-
flattenedInstList = append(flattenedInstList, instruction)
50-
}
51-
}
52-
44+
flattenedInstList := xml.Flatten((*structInfo).Instructions)
5345
for _, instruction := range flattenedInstList {
5446
switch instruction.XMLName.Local {
47+
case "array":
48+
fallthrough
5549
case "field":
56-
fieldTypeName, fieldTypeSize := GetInstructionTypeName(instruction)
50+
fieldTypeName, fieldTypeSize := GetInstructionTypeName(*instruction)
5751
if fieldTypeSize != "" {
5852
fieldTypeName = fieldTypeSize
5953
}
6054

6155
if instruction.Length != nil {
6256
if length, err := strconv.ParseInt(*instruction.Length, 10, 32); err == nil {
6357
// length is a numeric constant
64-
res += int(length)
58+
if fieldSize, err := CalculateTypeSize(fieldTypeName, fullSpec); err == nil {
59+
res += fieldSize * int(length)
60+
} else {
61+
return 0, err
62+
}
6563
} else {
6664
return 0, fmt.Errorf("instruction length %s must be a fixed size for %s (%s)", *instruction.Length, *instruction.Name, instruction.XMLName.Local)
6765
}
@@ -74,8 +72,6 @@ func CalculateTypeSize(typeName string, fullSpec xml.Protocol) (res int, err err
7472
}
7573
case "break":
7674
res += 1
77-
case "array":
78-
case "dummy":
7975
}
8076
}
8177

internal/xml/models.go

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ type ProtocolValue struct {
5353
}
5454

5555
type ProtocolInstruction struct {
56+
// XMLName is the XML element name of this instruction.
5657
XMLName xml.Name
58+
// IsChunked is True if this instruction appears within a "chunked" section
59+
IsChunked bool
60+
// ReferencedBy is the name of the instruction that references this instruction. This is only set for length instructions which are referenced by another instruction.
61+
ReferencedBy *string
5762

5863
// ProtocolField properties
5964
Name *string `xml:"name,attr"`
@@ -87,6 +92,8 @@ type ProtocolInstruction struct {
8792
}
8893

8994
type ProtocolCase struct {
95+
IsChunked bool
96+
9097
Value string `xml:"value,attr"`
9198
Default bool `xml:"default,attr"`
9299
Comment string `xml:"comment"`
@@ -95,19 +102,65 @@ type ProtocolCase struct {
95102

96103
type OrdinalValue int
97104

98-
func validate(instructions []ProtocolInstruction) error {
99-
for _, inst := range instructions {
105+
func Flatten(instructions []ProtocolInstruction) []*ProtocolInstruction {
106+
var flattenedInstList []*ProtocolInstruction
107+
for ndx, instruction := range instructions {
108+
if instruction.XMLName.Local == "chunked" {
109+
flattenedInstList = append(flattenedInstList, Flatten(instruction.Chunked)...)
110+
} else {
111+
// note: when flattening, switches are *not* flattened as they may have cases with instructions with name collisions
112+
// see: CharacterReplyServerPacket
113+
flattenedInstList = append(flattenedInstList, &instructions[ndx])
114+
}
115+
}
116+
return flattenedInstList
117+
}
118+
119+
func getLengthInstructions(instructions []ProtocolInstruction) (lengthInstructions []*ProtocolInstruction) {
120+
flattened := Flatten(instructions)
121+
for i, inst := range flattened {
122+
if inst.XMLName.Local == "length" {
123+
lengthInstructions = append(lengthInstructions, flattened[i])
124+
}
125+
}
126+
return
127+
}
128+
129+
func findLengthInstructionByName(lengthName string, lengthInstructions []*ProtocolInstruction) *ProtocolInstruction {
130+
for i, inst := range lengthInstructions {
131+
if inst.Name != nil && *inst.Name == lengthName {
132+
return lengthInstructions[i]
133+
}
134+
}
135+
return nil
136+
}
137+
138+
func validate(instructions []ProtocolInstruction, isChunked bool, lengthInstructions []*ProtocolInstruction) error {
139+
localLengths := append(lengthInstructions, getLengthInstructions(instructions)...)
140+
141+
for i, inst := range instructions {
142+
if isChunked {
143+
instructions[i].IsChunked = true
144+
}
145+
146+
if inst.Length != nil {
147+
if lengthInstruction := findLengthInstructionByName(*inst.Length, localLengths); lengthInstruction != nil {
148+
lengthInstruction.ReferencedBy = new(string)
149+
*lengthInstruction.ReferencedBy = *inst.Name
150+
}
151+
}
152+
100153
if err := inst.Validate(); err != nil {
101154
return err
102155
}
103156

104-
if err := validate(inst.Chunked); err != nil {
157+
if err := validate(inst.Chunked, true, localLengths); err != nil {
105158
return err
106159
}
107160

108161
if len(inst.Cases) > 0 {
109162
for _, cs := range inst.Cases {
110-
if err := validate(cs.Instructions); err != nil {
163+
if err := validate(cs.Instructions, isChunked, localLengths); err != nil {
111164
return err
112165
}
113166
}
@@ -119,13 +172,13 @@ func validate(instructions []ProtocolInstruction) error {
119172

120173
func (p Protocol) Validate() error {
121174
for _, st := range p.Structs {
122-
if err := validate(st.Instructions); err != nil {
175+
if err := validate(st.Instructions, false, nil); err != nil {
123176
return err
124177
}
125178
}
126179

127180
for _, pkt := range p.Packets {
128-
if err := validate(pkt.Instructions); err != nil {
181+
if err := validate(pkt.Instructions, false, nil); err != nil {
129182
return err
130183
}
131184
}
@@ -199,7 +252,7 @@ func (pi ProtocolInstruction) Validate() error {
199252
fieldName := reflectType.Field(i)
200253
fieldValue := reflectValue.Field(i)
201254

202-
if fieldName.Name == "XMLName" {
255+
if fieldName.Name == "XMLName" || fieldName.Name == "IsChunked" || fieldName.Name == "ReferencedBy" {
203256
continue
204257
}
205258

0 commit comments

Comments
 (0)