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
|
package graph
import (
core "github.com/authzed/spicedb/pkg/proto/core/v1"
"github.com/authzed/spicedb/pkg/spiceerrors"
)
// WalkHandler is a function invoked for each node in the rewrite tree. If it returns non-nil,
// that value is returned from the walk. Otherwise, the walk continues.
type WalkHandler func(childOneof *core.SetOperation_Child) (interface{}, error)
// WalkRewrite walks a userset rewrite tree, invoking the handler found on each node of the tree
// until the handler returns a non-nil value, which is in turn returned from this function. Returns
// nil if no valid value was found. If the rewrite is nil, returns nil.
func WalkRewrite(rewrite *core.UsersetRewrite, handler WalkHandler) (interface{}, error) {
if rewrite == nil {
return nil, nil
}
switch rw := rewrite.RewriteOperation.(type) {
case *core.UsersetRewrite_Union:
return walkRewriteChildren(rw.Union, handler)
case *core.UsersetRewrite_Intersection:
return walkRewriteChildren(rw.Intersection, handler)
case *core.UsersetRewrite_Exclusion:
return walkRewriteChildren(rw.Exclusion, handler)
default:
return nil, spiceerrors.MustBugf("unknown type of rewrite operation in walker: %T", rw)
}
}
// HasThis returns true if there exists a `_this` node anywhere within the given rewrite. If
// the rewrite is nil, returns false.
func HasThis(rewrite *core.UsersetRewrite) (bool, error) {
result, err := WalkRewrite(rewrite, func(childOneof *core.SetOperation_Child) (interface{}, error) {
switch childOneof.ChildType.(type) {
case *core.SetOperation_Child_XThis:
return true, nil
default:
return nil, nil
}
})
return result != nil && result.(bool), err
}
func walkRewriteChildren(so *core.SetOperation, handler WalkHandler) (interface{}, error) {
for _, childOneof := range so.Child {
vle, err := handler(childOneof)
if err != nil {
return nil, err
}
if vle != nil {
return vle, nil
}
switch child := childOneof.ChildType.(type) {
case *core.SetOperation_Child_UsersetRewrite:
rvle, err := WalkRewrite(child.UsersetRewrite, handler)
if err != nil {
return nil, err
}
if rvle != nil {
return rvle, nil
}
}
}
return nil, nil
}
|