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

mlange-42 / arche-serde / 7488271365

11 Jan 2024 11:45AM CUT coverage: 85.124% (+1.4%) from 83.766%
7488271365

Pull #3

github

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

206 of 242 relevant lines covered (85.12%)

29.18 hits per line

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

78.31
/deserialize.go
1
package archeserde
2

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

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

11
// Deserialize an Arche [ecs.World] from JSON.
12
//
13
// The world must be prepared the following way:
14
//   - All required component types must be registered using [ecs.ComponentID]
15
//   - All required resources must be added using [ecs.AddResource]
16
//
17
// After deserialization, it is not guaranteed that entity iteration order in queries is the same as before.
18
func Deserialize(jsonData []byte, world *ecs.World) error {
3✔
19
        infos := map[ecs.ID]ecs.CompInfo{}
3✔
20
        ids := map[string]ecs.ID{}
3✔
21
        for i := 0; i < ecs.MaskTotalBits; i++ {
771✔
22
                if info, ok := ecs.ComponentInfo(world, ecs.ID(i)); ok {
773✔
23
                        infos[ecs.ID(i)] = info
5✔
24
                        ids[info.Type.String()] = ecs.ID(i)
5✔
25
                }
5✔
26
        }
27

28
        resTypes := map[ecs.ResID]reflect.Type{}
3✔
29
        resIds := map[string]ecs.ResID{}
3✔
30
        for i := 0; i < ecs.MaskTotalBits; i++ {
771✔
31
                if tp, ok := ecs.ResourceType(world, ecs.ResID(i)); ok {
770✔
32
                        resTypes[ecs.ResID(i)] = tp
2✔
33
                        resIds[tp.String()] = ecs.ResID(i)
2✔
34
                }
2✔
35
        }
36

37
        deserial := deserializer{}
3✔
38

3✔
39
        if err := json.Unmarshal(jsonData, &deserial); err != nil {
3✔
40
                return err
×
41
        }
×
42

43
        world.SetEntityData(&deserial.World)
3✔
44

3✔
45
        for _, tp := range deserial.Types {
8✔
46
                if _, ok := ids[tp]; !ok {
5✔
47
                        return fmt.Errorf("component type is not registered: %s", tp)
×
48
                }
×
49
        }
50

51
        for i, comps := range deserial.Components {
8✔
52
                entity := deserial.Entities[i]
5✔
53

5✔
54
                mp := map[string]entry{}
5✔
55

5✔
56
                if err := json.Unmarshal(comps.Bytes, &mp); err != nil {
5✔
57
                        return err
×
58
                }
×
59

60
                target := ecs.Entity{}
5✔
61
                var targetComp ecs.ID
5✔
62
                components := []ecs.Component{}
5✔
63
                for tpName, value := range mp {
16✔
64
                        if tpName == targetTag {
13✔
65
                                if err := json.Unmarshal(value.Bytes, &target); err != nil {
2✔
66
                                        return err
×
67
                                }
×
68
                                continue
2✔
69
                        }
70

71
                        id := ids[tpName]
9✔
72
                        info := infos[id]
9✔
73

9✔
74
                        if info.IsRelation {
11✔
75
                                targetComp = id
2✔
76
                        }
2✔
77

78
                        component := reflect.New(info.Type).Interface()
9✔
79
                        if err := json.Unmarshal(value.Bytes, &component); err != nil {
9✔
80
                                return err
×
81
                        }
×
82
                        components = append(components, ecs.Component{
9✔
83
                                ID:   id,
9✔
84
                                Comp: component,
9✔
85
                        })
9✔
86
                }
87

88
                world.Assign(entity, components...)
5✔
89
                if !target.IsZero() {
6✔
90
                        world.Relations().Set(entity, targetComp, target)
1✔
91
                }
1✔
92
        }
93

94
        for tpName, res := range deserial.Resources {
5✔
95
                resID, ok := resIds[tpName]
2✔
96
                if !ok {
2✔
97
                        return fmt.Errorf("resource type is not registered: %s", tpName)
×
98
                }
×
99

100
                tp := resTypes[resID]
2✔
101
                resource := reflect.New(tp).Interface()
2✔
102
                if err := json.Unmarshal(res.Bytes, &resource); err != nil {
2✔
103
                        return err
×
104
                }
×
105

106
                resLoc := world.Resources().Get(resID)
2✔
107
                if resLoc == nil {
2✔
108
                        return fmt.Errorf("resource type registered but nil: %s", tpName)
×
109
                }
×
110

111
                rValue := reflect.ValueOf(resLoc)
2✔
112
                ptr := rValue.UnsafePointer()
2✔
113
                value := reflect.NewAt(tp, ptr).Interface()
2✔
114

2✔
115
                if err := json.Unmarshal(res.Bytes, &value); err != nil {
2✔
116
                        return err
×
117
                }
×
118
        }
119

120
        return nil
3✔
121
}
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