summaryrefslogtreecommitdiff
path: root/vendor/github.com/authzed/spicedb/pkg/graph/walker.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/authzed/spicedb/pkg/graph/walker.go')
-rw-r--r--vendor/github.com/authzed/spicedb/pkg/graph/walker.go71
1 files changed, 71 insertions, 0 deletions
diff --git a/vendor/github.com/authzed/spicedb/pkg/graph/walker.go b/vendor/github.com/authzed/spicedb/pkg/graph/walker.go
new file mode 100644
index 0000000..3ae8b6b
--- /dev/null
+++ b/vendor/github.com/authzed/spicedb/pkg/graph/walker.go
@@ -0,0 +1,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
+}