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

mlange-42 / arche-serde / 7487858638

11 Jan 2024 11:05AM CUT coverage: 83.468% (-0.3%) from 83.766%
7487858638

Pull #3

github

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

207 of 248 relevant lines covered (83.47%)

28.39 hits per line

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

79.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
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
        world.SetEntityData(&deserial.World)
3✔
42

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

49
        entityMap := map[ecs.Entity]int{}
3✔
50
        for idx, entity := range deserial.Entities {
8✔
51
                entityMap[entity] = idx
5✔
52
        }
5✔
53

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

5✔
57
                mp := map[string]entry{}
5✔
58

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

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

74
                        id := ids[tpName]
9✔
75
                        info := infos[id]
9✔
76

9✔
77
                        if info.IsRelation {
11✔
78
                                targetComp = id
2✔
79
                        }
2✔
80

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

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

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

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

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

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

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

123
        return nil
3✔
124
}
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