• 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

77.27
/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
func Deserialize(jsonData []byte, world *ecs.World) error {
3✔
17
        infos := map[ecs.ID]ecs.CompInfo{}
3✔
18
        ids := map[string]ecs.ID{}
3✔
19
        for i := 0; i < ecs.MaskTotalBits; i++ {
771✔
20
                if info, ok := ecs.ComponentInfo(world, ecs.ID(i)); ok {
773✔
21
                        infos[ecs.ID(i)] = info
5✔
22
                        ids[info.Type.String()] = ecs.ID(i)
5✔
23
                }
5✔
24
        }
25

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

35
        deserial := deserializer{}
3✔
36

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

41
        if err := world.UnmarshalEntities(deserial.World.Bytes); err != nil {
3✔
42
                return err
×
43
        }
×
44

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
        entityMap := map[ecs.Entity]int{}
3✔
52
        for idx, entity := range deserial.Entities {
8✔
53
                entityMap[entity] = idx
5✔
54
        }
5✔
55

56
        for i, comps := range deserial.Components {
8✔
57
                entity := deserial.Entities[i]
5✔
58

5✔
59
                mp := map[string]entry{}
5✔
60

5✔
61
                if err := json.Unmarshal(comps.Bytes, &mp); err != nil {
5✔
62
                        return err
×
63
                }
×
64

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

76
                        id := ids[tpName]
9✔
77
                        info := infos[id]
9✔
78

9✔
79
                        if info.IsRelation {
11✔
80
                                targetComp = id
2✔
81
                        }
2✔
82

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

93
                world.Assign(entity, components...)
5✔
94
                if !target.IsZero() {
6✔
95
                        world.Relations().Set(entity, targetComp, target)
1✔
96
                }
1✔
97
        }
98

99
        for tpName, res := range deserial.Resources {
4✔
100
                resID, ok := resIds[tpName]
1✔
101
                if !ok {
1✔
102
                        return fmt.Errorf("resource type is not registered: %s", tpName)
×
103
                }
×
104

105
                tp := resTypes[resID]
1✔
106
                resource := reflect.New(tp).Interface()
1✔
107
                if err := json.Unmarshal(res.Bytes, &resource); err != nil {
1✔
108
                        return err
×
109
                }
×
110

111
                resLoc := world.Resources().Get(resID)
1✔
112
                if resLoc == nil {
1✔
113
                        return fmt.Errorf("resource type registered but nil: %s", tpName)
×
114
                }
×
115

116
                rValue := reflect.ValueOf(resLoc)
1✔
117
                ptr := rValue.UnsafePointer()
1✔
118
                value := reflect.NewAt(tp, ptr).Interface()
1✔
119

1✔
120
                if err := json.Unmarshal(res.Bytes, &value); err != nil {
1✔
121
                        return err
×
122
                }
×
123
        }
124

125
        return nil
3✔
126
}
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