• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / arche-serde / 7482715465

11 Jan 2024 12:52AM CUT coverage: 83.197% (-0.6%) from 83.766%
7482715465

Pull #3

github

web-flow
Merge 116180906 into 8937cb386
Pull Request #3: Serialize entity relations

203 of 244 relevant lines covered (83.2%)

28.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.92
/serialize.go
1
package archeserde
2

3
import (
4
        "encoding/json"
5
        "fmt"
6
        "reflect"
7
        "strings"
8

9
        "github.com/mlange-42/arche/ecs"
10
)
11

12
const targetTag = "arche.relation.Target"
13

14
// Serialize an Arche ECS world to JSON.
15
func Serialize(world *ecs.World) ([]byte, error) {
3✔
16
        builder := strings.Builder{}
3✔
17

3✔
18
        builder.WriteString("{\n")
3✔
19

3✔
20
        if err := serializeWorld(world, &builder); err != nil {
3✔
21
                return nil, err
×
22
        }
×
23
        builder.WriteString(",\n")
3✔
24

3✔
25
        serializeTypes(world, &builder)
3✔
26
        builder.WriteString(",\n")
3✔
27

3✔
28
        if err := serializeEntities(world, &builder); err != nil {
3✔
29
                return nil, err
×
30
        }
×
31
        builder.WriteString(",\n")
3✔
32

3✔
33
        if err := serializeComponents(world, &builder); err != nil {
3✔
34
                return nil, err
×
35
        }
×
36
        builder.WriteString(",\n")
3✔
37

3✔
38
        if err := serializeResources(world, &builder); err != nil {
3✔
39
                return nil, err
×
40
        }
×
41
        builder.WriteString("}\n")
3✔
42

3✔
43
        return []byte(builder.String()), nil
3✔
44
}
45

46
func serializeWorld(world *ecs.World, builder *strings.Builder) error {
3✔
47
        jsonData, err := world.MarshalEntities()
3✔
48
        if err != nil {
3✔
49
                return err
×
50
        }
×
51
        builder.WriteString(fmt.Sprintf("\"World\" : %s", string(jsonData)))
3✔
52
        return nil
3✔
53
}
54

55
func serializeTypes(world *ecs.World, builder *strings.Builder) {
3✔
56
        builder.WriteString("\"Types\" : [\n")
3✔
57

3✔
58
        types := map[ecs.ID]reflect.Type{}
3✔
59
        for i := 0; i < ecs.MaskTotalBits; i++ {
771✔
60
                if info, ok := ecs.ComponentInfo(world, ecs.ID(i)); ok {
773✔
61
                        types[ecs.ID(i)] = info.Type
5✔
62
                }
5✔
63
        }
64
        maxComp := len(types) - 1
3✔
65
        counter := 0
3✔
66
        for _, tp := range types {
8✔
67
                builder.WriteString(fmt.Sprintf("  \"%s\"", tp.String()))
5✔
68
                if counter < maxComp {
8✔
69
                        builder.WriteString(",")
3✔
70
                }
3✔
71
                builder.WriteString("\n")
5✔
72
                counter++
5✔
73
        }
74

75
        builder.WriteString("]")
3✔
76
}
77

78
func serializeEntities(world *ecs.World, builder *strings.Builder) error {
3✔
79

3✔
80
        builder.WriteString("\"Entities\" : [\n")
3✔
81

3✔
82
        query := world.Query(ecs.All())
3✔
83
        lastEntity := query.Count() - 1
3✔
84
        counter := 0
3✔
85
        for query.Next() {
8✔
86
                jsonData, err := json.Marshal(query.Entity())
5✔
87
                if err != nil {
5✔
88
                        return err
×
89
                }
×
90
                builder.WriteString(fmt.Sprintf("    %s", jsonData))
5✔
91
                if counter < lastEntity {
8✔
92
                        builder.WriteString(",")
3✔
93
                }
3✔
94
                builder.WriteString("\n")
5✔
95

5✔
96
                counter++
5✔
97
        }
98
        builder.WriteString("]")
3✔
99

3✔
100
        return nil
3✔
101
}
102

103
func serializeComponents(world *ecs.World, builder *strings.Builder) error {
3✔
104

3✔
105
        builder.WriteString("\"Components\" : [\n")
3✔
106

3✔
107
        query := world.Query(ecs.All())
3✔
108
        lastEntity := query.Count() - 1
3✔
109
        counter := 0
3✔
110
        for query.Next() {
8✔
111
                builder.WriteString("  {\n")
5✔
112

5✔
113
                ids := query.Ids()
5✔
114
                last := len(ids) - 1
5✔
115

5✔
116
                for i, id := range ids {
14✔
117
                        info, _ := ecs.ComponentInfo(world, id)
9✔
118

9✔
119
                        if info.IsRelation {
11✔
120
                                target := query.Relation(id)
2✔
121
                                builder.WriteString(fmt.Sprintf("    \"%s\" : {\"ID\": %d, \"Gen\": %d},\n", targetTag, target.ID(), target.Gen()))
2✔
122
                        }
2✔
123

124
                        comp := query.Get(id)
9✔
125
                        value := reflect.NewAt(info.Type, comp).Interface()
9✔
126
                        jsonData, err := json.Marshal(value)
9✔
127
                        if err != nil {
9✔
128
                                return err
×
129
                        }
×
130
                        builder.WriteString(fmt.Sprintf("    \"%s\" : ", info.Type.String()))
9✔
131
                        builder.WriteString(string(jsonData))
9✔
132
                        if i < last {
13✔
133
                                builder.WriteString(",")
4✔
134
                        }
4✔
135
                        builder.WriteString("\n")
9✔
136
                }
137

138
                builder.WriteString("  }")
5✔
139
                if counter < lastEntity {
8✔
140
                        builder.WriteString(",")
3✔
141
                }
3✔
142
                builder.WriteString("\n")
5✔
143

5✔
144
                counter++
5✔
145
        }
146
        builder.WriteString("]")
3✔
147

3✔
148
        return nil
3✔
149
}
150

151
func serializeResources(world *ecs.World, builder *strings.Builder) error {
3✔
152
        builder.WriteString("\"Resources\" : {\n")
3✔
153

3✔
154
        resTypes := map[ecs.ResID]reflect.Type{}
3✔
155
        for i := 0; i < ecs.MaskTotalBits; i++ {
771✔
156
                if tp, ok := ecs.ResourceType(world, ecs.ResID(i)); ok {
769✔
157
                        resTypes[ecs.ResID(i)] = tp
1✔
158
                }
1✔
159
        }
160

161
        last := len(resTypes) - 1
3✔
162
        counter := 0
3✔
163
        for id, tp := range resTypes {
4✔
164
                res := world.Resources().Get(id)
1✔
165
                rValue := reflect.ValueOf(res)
1✔
166
                ptr := rValue.UnsafePointer()
1✔
167

1✔
168
                value := reflect.NewAt(tp, ptr).Interface()
1✔
169
                jsonData, err := json.Marshal(value)
1✔
170
                if err != nil {
1✔
171
                        return err
×
172
                }
×
173

174
                builder.WriteString("    ")
1✔
175
                builder.WriteString(fmt.Sprintf("\"%s\" : ", tp.String()))
1✔
176
                builder.WriteString(string(jsonData))
1✔
177

1✔
178
                if counter < last {
1✔
179
                        builder.WriteString(",")
×
180
                }
×
181
                builder.WriteString("\n")
1✔
182
        }
183

184
        builder.WriteString("}")
3✔
185

3✔
186
        return nil
3✔
187
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc