forked from iotaledger/goshimmer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
99 lines (82 loc) · 4.16 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package conflictdag
import (
"context"
"github.com/izuc/zipp.foundation/core/generics/lo"
"github.com/izuc/zipp.foundation/core/generics/objectstorage"
"github.com/izuc/zipp.foundation/core/generics/set"
"github.com/izuc/zipp.foundation/core/generics/walker"
"github.com/izuc/zipp.foundation/core/serix"
)
// Utils is a ConflictDAG component that bundles utility related API to simplify common interactions with the ConflictDAG.
type Utils[ConflictID comparable, ConflictSetID comparable] struct {
// conflictDAG contains a reference to the ConflictDAG that created the Utils.
conflictDAG *ConflictDAG[ConflictID, ConflictSetID]
}
// newUtils returns a new Utils instance for the given ConflictDAG.
func newUtils[ConflictID comparable, ConflictSetID comparable](conflictDAG *ConflictDAG[ConflictID, ConflictSetID]) (new *Utils[ConflictID, ConflictSetID]) {
return &Utils[ConflictID, ConflictSetID]{
conflictDAG: conflictDAG,
}
}
func (u *Utils[ConflictID, ConflictSetID]) ForEachChildConflictID(conflictID ConflictID, callback func(childConflictID ConflictID)) {
u.conflictDAG.Storage.CachedChildConflicts(conflictID).Consume(func(childConflict *ChildConflict[ConflictID]) {
callback(childConflict.ChildConflictID())
})
}
// ForEachConflict iterates over every existing Conflict in the entire Storage.
func (u *Utils[ConflictID, ConflictSetID]) ForEachConflict(consumer func(conflict *Conflict[ConflictID, ConflictSetID])) {
u.conflictDAG.Storage.conflictStorage.ForEach(func(key []byte, cachedObject *objectstorage.CachedObject[*Conflict[ConflictID, ConflictSetID]]) bool {
cachedObject.Consume(func(conflict *Conflict[ConflictID, ConflictSetID]) {
consumer(conflict)
})
return true
})
}
// ForEachConflictingConflictID executes the callback for each Conflict that is conflicting with the named Conflict.
func (u *Utils[ConflictID, ConflictSetID]) ForEachConflictingConflictID(conflictID ConflictID, callback func(conflictingConflictID ConflictID) bool) {
u.conflictDAG.Storage.CachedConflict(conflictID).Consume(func(conflict *Conflict[ConflictID, ConflictSetID]) {
u.forEachConflictingConflictID(conflict, callback)
})
}
// ForEachConnectedConflictingConflictID executes the callback for each Conflict that is directly or indirectly connected to
// the named Conflict through a chain of intersecting conflicts.
func (u *Utils[ConflictID, ConflictSetID]) ForEachConnectedConflictingConflictID(conflictID ConflictID, callback func(conflictingConflictID ConflictID)) {
traversedConflicts := set.New[ConflictID]()
conflictSetsWalker := walker.New[ConflictSetID]()
processConflictAndQueueConflictSets := func(conflictID ConflictID) {
if !traversedConflicts.Add(conflictID) {
return
}
u.conflictDAG.Storage.CachedConflict(conflictID).Consume(func(conflict *Conflict[ConflictID, ConflictSetID]) {
_ = conflict.ConflictSetIDs().ForEach(func(conflictSetID ConflictSetID) (err error) {
conflictSetsWalker.Push(conflictSetID)
return nil
})
})
}
processConflictAndQueueConflictSets(conflictID)
for conflictSetsWalker.HasNext() {
u.conflictDAG.Storage.CachedConflictMembers(conflictSetsWalker.Next()).Consume(func(conflictMember *ConflictMember[ConflictSetID, ConflictID]) {
processConflictAndQueueConflictSets(conflictMember.ConflictID())
})
}
traversedConflicts.ForEach(callback)
}
// forEachConflictingConflictID executes the callback for each Conflict that is conflicting with the named Conflict.
func (u *Utils[ConflictID, ConflictSetID]) forEachConflictingConflictID(conflict *Conflict[ConflictID, ConflictSetID], callback func(conflictingConflictID ConflictID) bool) {
for it := conflict.ConflictSetIDs().Iterator(); it.HasNext(); {
abort := false
u.conflictDAG.Storage.CachedConflictMembers(it.Next()).Consume(func(conflictMember *ConflictMember[ConflictSetID, ConflictID]) {
if abort || conflictMember.ConflictID() == conflict.ID() {
return
}
if abort = !callback(conflictMember.ConflictID()); abort {
it.StopWalk()
}
})
}
}
// bytes is an internal utility function that simplifies the serialization of the identifier types.
func bytes(obj interface{}) (bytes []byte) {
return lo.PanicOnErr(serix.DefaultAPI.Encode(context.Background(), obj))
}