feat: wildcard

This commit is contained in:
Alan Shaw
2024-08-21 08:13:44 +02:00
parent ce8008b650
commit e30a776aaa
3 changed files with 83 additions and 24 deletions

View File

@@ -63,11 +63,11 @@ func matchStatement(statement Statement, node ipld.Node) bool {
}
return isOrdered(s.Value(), one, lte)
}
case Kind_Negation:
case Kind_Not:
if s, ok := statement.(NegationStatement); ok {
return !matchStatement(s.Value(), node)
}
case Kind_Conjunction:
case Kind_And:
if s, ok := statement.(ConjunctionStatement); ok {
for _, cs := range s.Value() {
r := matchStatement(cs, node)
@@ -77,7 +77,7 @@ func matchStatement(statement Statement, node ipld.Node) bool {
}
return true
}
case Kind_Disjunction:
case Kind_Or:
if s, ok := statement.(DisjunctionStatement); ok {
if len(s.Value()) == 0 {
return true
@@ -90,9 +90,20 @@ func matchStatement(statement Statement, node ipld.Node) bool {
}
return false
}
case Kind_Wildcard:
case Kind_Universal:
case Kind_Existential:
case Kind_Like:
if s, ok := statement.(WildcardStatement); ok {
one, _, err := selector.Select(s.Selector(), node)
if err != nil || one == nil {
return false
}
v, err := one.AsString()
if err != nil {
return false
}
return s.Value().Match(v)
}
case Kind_All:
case Kind_Any:
}
panic(fmt.Errorf("unimplemented statement kind: %s", statement.Kind()))
}

View File

@@ -1,8 +1,10 @@
package policy
import (
"fmt"
"testing"
"github.com/gobwas/glob"
"github.com/ipfs/go-cid"
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
"github.com/ipld/go-ipld-prime/node/basicnode"
@@ -284,4 +286,49 @@ func TestMatch(t *testing.T) {
ok = Match(pol, nd)
require.True(t, ok)
})
t.Run("wildcard", func(t *testing.T) {
glb, err := glob.Compile(`Alice\*, Bob*, Carol.`)
require.NoError(t, err)
for _, s := range []string{
"Alice*, Bob, Carol.",
"Alice*, Bob, Dan, Erin, Carol.",
"Alice*, Bob , Carol.",
"Alice*, Bob*, Carol.",
} {
func(s string) {
t.Run(fmt.Sprintf("pass %s", s), func(t *testing.T) {
np := basicnode.Prototype.String
nb := np.NewBuilder()
nb.AssignString(s)
nd := nb.Build()
pol := Policy{Like(selector.MustParse("."), glb)}
ok := Match(pol, nd)
require.True(t, ok)
})
}(s)
}
for _, s := range []string{
"Alice*, Bob, Carol",
"Alice*, Bob*, Carol!",
"Alice, Bob, Carol.",
" Alice*, Bob, Carol. ",
} {
func(s string) {
t.Run(fmt.Sprintf("fail %s", s), func(t *testing.T) {
np := basicnode.Prototype.String
nb := np.NewBuilder()
nb.AssignString(s)
nd := nb.Build()
pol := Policy{Like(selector.MustParse("."), glb)}
ok := Match(pol, nd)
require.False(t, ok)
})
}(s)
}
})
}

View File

@@ -3,6 +3,7 @@ package policy
// https://github.com/ucan-wg/delegation/blob/4094d5878b58f5d35055a3b93fccda0b8329ebae/README.md#policy
import (
"github.com/gobwas/glob"
"github.com/ipld/go-ipld-prime"
"github.com/storacha-network/go-ucanto/core/policy/selector"
)
@@ -13,12 +14,12 @@ const (
Kind_GreaterThanOrEqual = ">="
Kind_LessThan = "<"
Kind_LessThanOrEqual = "<="
Kind_Negation = "not"
Kind_Conjunction = "and"
Kind_Disjunction = "or"
Kind_Wildcard = "like"
Kind_Universal = "all"
Kind_Existential = "any"
Kind_Not = "not"
Kind_And = "and"
Kind_Or = "or"
Kind_Like = "like"
Kind_All = "all"
Kind_Any = "any"
)
type Policy = []Statement
@@ -42,7 +43,7 @@ type InequalityStatement interface {
type WildcardStatement interface {
Statement
Selector() selector.Selector
Value() string
Value() glob.Glob
}
type ConnectiveStatement interface {
@@ -113,7 +114,7 @@ type negation struct {
}
func (n negation) Kind() string {
return Kind_Negation
return Kind_Not
}
func (n negation) Value() Statement {
@@ -129,7 +130,7 @@ type conjunction struct {
}
func (n conjunction) Kind() string {
return Kind_Conjunction
return Kind_And
}
func (n conjunction) Value() []Statement {
@@ -145,7 +146,7 @@ type disjunction struct {
}
func (n disjunction) Kind() string {
return Kind_Disjunction
return Kind_Or
}
func (n disjunction) Value() []Statement {
@@ -158,23 +159,23 @@ func Or(stmts ...Statement) DisjunctionStatement {
type wildcard struct {
selector selector.Selector
pattern string
glob glob.Glob
}
func (n wildcard) Kind() string {
return Kind_Wildcard
return Kind_Like
}
func (n wildcard) Selector() selector.Selector {
return n.selector
}
func (n wildcard) Value() string {
return n.pattern
func (n wildcard) Value() glob.Glob {
return n.glob
}
func Like(selector selector.Selector, pattern string) WildcardStatement {
return wildcard{selector, pattern}
func Like(selector selector.Selector, glob glob.Glob) WildcardStatement {
return wildcard{selector, glob}
}
type quantifier struct {
@@ -196,9 +197,9 @@ func (n quantifier) Value() Policy {
}
func All(selector selector.Selector, policy Policy) QuantifierStatement {
return quantifier{Kind_Universal, selector, policy}
return quantifier{Kind_All, selector, policy}
}
func Any(selector selector.Selector, policy Policy) QuantifierStatement {
return quantifier{Kind_Existential, selector, policy}
return quantifier{Kind_Any, selector, policy}
}