use generic functions for dealing with lists.

This commit is contained in:
fiatjaf 2022-11-08 07:15:08 -03:00
parent c4d52e516f
commit f98f54d3be
No known key found for this signature in database
GPG Key ID: BAD43C4BE5C1A3A1
7 changed files with 50 additions and 82 deletions

View File

@ -7,9 +7,10 @@ import (
"time"
"github.com/valyala/fastjson"
"golang.org/x/exp/slices"
)
type Tags []StringList
type Tags [][]string
func (t *Tags) Scan(src interface{}) error {
var jtags []byte = make([]byte, 0)
@ -27,7 +28,7 @@ func (t *Tags) Scan(src interface{}) error {
return nil
}
func (tags Tags) ContainsAny(tagName string, values StringList) bool {
func (tags Tags) ContainsAny(tagName string, values []string) bool {
for _, tag := range tags {
if len(tag) < 2 {
continue
@ -37,7 +38,7 @@ func (tags Tags) ContainsAny(tagName string, values StringList) bool {
continue
}
if values.Contains(tag[1]) {
if slices.Contains(values, tag[1]) {
return true
}
}
@ -146,14 +147,14 @@ func fastjsonArrayToTags(v *fastjson.Value) (Tags, error) {
return nil, err
}
sll := make([]StringList, len(arr))
sll := make([][]string, len(arr))
for i, v := range arr {
subarr, err := v.Array()
if err != nil {
return nil, err
}
sl := make(StringList, len(subarr))
sl := make([]string, len(subarr))
for j, subv := range subarr {
sb, err := subv.StringBytes()
if err != nil {

View File

@ -2,21 +2,23 @@ package nostr
import (
"time"
"golang.org/x/exp/slices"
)
type Filters []Filter
type Filter struct {
IDs StringList
Kinds IntList
Authors StringList
IDs []string
Kinds []int
Authors []string
Tags TagMap
Since *time.Time
Until *time.Time
Limit int
}
type TagMap map[string]StringList
type TagMap map[string][]string
func (eff Filters) Match(event *Event) bool {
for _, filter := range eff {
@ -32,15 +34,15 @@ func (ef Filter) Matches(event *Event) bool {
return false
}
if ef.IDs != nil && !ef.IDs.ContainsPrefixOf(event.ID) {
if ef.IDs != nil && !ContainsPrefixOf(ef.IDs, event.ID) {
return false
}
if ef.Kinds != nil && !ef.Kinds.Contains(event.Kind) {
if ef.Kinds != nil && !slices.Contains(ef.Kinds, event.Kind) {
return false
}
if ef.Authors != nil && !ef.Authors.ContainsPrefixOf(event.PubKey) {
if ef.Authors != nil && !ContainsPrefixOf(ef.Authors, event.PubKey) {
return false
}
@ -62,15 +64,15 @@ func (ef Filter) Matches(event *Event) bool {
}
func FilterEqual(a Filter, b Filter) bool {
if !a.Kinds.Equals(b.Kinds) {
if !Similar(a.Kinds, b.Kinds) {
return false
}
if !a.IDs.Equals(b.IDs) {
if !Similar(a.IDs, b.IDs) {
return false
}
if !a.Authors.Equals(b.Authors) {
if !Similar(a.Authors, b.Authors) {
return false
}
@ -82,7 +84,7 @@ func FilterEqual(a Filter, b Filter) bool {
if bv, ok := b.Tags[f]; !ok {
return false
} else {
if !av.Equals(bv) {
if !Similar(av, bv) {
return false
}
}

View File

@ -109,7 +109,7 @@ func (f Filter) MarshalJSON() ([]byte, error) {
return o.MarshalTo(nil), nil
}
func stringListToFastjsonArray(arena *fastjson.Arena, sl StringList) *fastjson.Value {
func stringListToFastjsonArray(arena *fastjson.Arena, sl []string) *fastjson.Value {
arr := arena.NewArray()
for i, v := range sl {
arr.SetArrayItem(i, arena.NewString(v))
@ -117,7 +117,7 @@ func stringListToFastjsonArray(arena *fastjson.Arena, sl StringList) *fastjson.V
return arr
}
func intListToFastjsonArray(arena *fastjson.Arena, il IntList) *fastjson.Value {
func intListToFastjsonArray(arena *fastjson.Arena, il []int) *fastjson.Value {
arr := arena.NewArray()
for i, v := range il {
arr.SetArrayItem(i, arena.NewNumberInt(v))
@ -125,13 +125,13 @@ func intListToFastjsonArray(arena *fastjson.Arena, il IntList) *fastjson.Value {
return arr
}
func fastjsonArrayToStringList(v *fastjson.Value) (StringList, error) {
func fastjsonArrayToStringList(v *fastjson.Value) ([]string, error) {
arr, err := v.Array()
if err != nil {
return nil, err
}
sl := make(StringList, len(arr))
sl := make([]string, len(arr))
for i, v := range arr {
sb, err := v.StringBytes()
if err != nil {
@ -143,13 +143,13 @@ func fastjsonArrayToStringList(v *fastjson.Value) (StringList, error) {
return sl, nil
}
func fastjsonArrayToIntList(v *fastjson.Value) (IntList, error) {
func fastjsonArrayToIntList(v *fastjson.Value) ([]int, error) {
arr, err := v.Array()
if err != nil {
return nil, err
}
il := make(IntList, len(arr))
il := make([]int, len(arr))
for i, v := range arr {
il[i], err = v.Int()
if err != nil {

View File

@ -4,6 +4,8 @@ import (
"encoding/json"
"testing"
"time"
"golang.org/x/exp/slices"
)
func TestFilterUnmarshal(t *testing.T) {
@ -16,7 +18,7 @@ func TestFilterUnmarshal(t *testing.T) {
if f.Since == nil || f.Since.Format("2006-01-02") != "2022-02-07" ||
f.Until != nil ||
f.Tags == nil || len(f.Tags) != 2 || !f.Tags["something"].Contains("bab") {
f.Tags == nil || len(f.Tags) != 2 || !slices.Contains(f.Tags["something"], "bab") {
t.Error("failed to parse filter correctly")
}
}
@ -25,7 +27,7 @@ func TestFilterMarshal(t *testing.T) {
tm := time.Unix(12345678, 0)
filterj, err := json.Marshal(Filter{
Kinds: IntList{1, 2, 4},
Kinds: []int{1, 2, 4},
Tags: TagMap{"fruit": {"banana", "mango"}},
Until: &tm,
})
@ -40,20 +42,20 @@ func TestFilterMarshal(t *testing.T) {
}
func TestFilterMatching(t *testing.T) {
if (Filter{Kinds: IntList{4, 5}}).Matches(&Event{Kind: 6}) {
if (Filter{Kinds: []int{4, 5}}).Matches(&Event{Kind: 6}) {
t.Error("matched event that shouldn't have matched")
}
if !(Filter{Kinds: IntList{4, 5}}).Matches(&Event{Kind: 4}) {
if !(Filter{Kinds: []int{4, 5}}).Matches(&Event{Kind: 4}) {
t.Error("failed to match event by kind")
}
if !(Filter{
Kinds: IntList{4, 5},
Kinds: []int{4, 5},
Tags: TagMap{
"p": {"ooo"},
},
IDs: StringList{"prefix"},
IDs: []string{"prefix"},
}).Matches(&Event{
Kind: 4,
Tags: Tags{{"p", "ooo", ",x,x,"}, {"m", "yywyw", "xxx"}},
@ -65,15 +67,15 @@ func TestFilterMatching(t *testing.T) {
func TestFilterEquality(t *testing.T) {
if !FilterEqual(
Filter{Kinds: IntList{4, 5}},
Filter{Kinds: IntList{4, 5}},
Filter{Kinds: []int{4, 5}},
Filter{Kinds: []int{4, 5}},
) {
t.Error("kinds filters should be equal")
}
if !FilterEqual(
Filter{Kinds: IntList{4, 5}, Tags: TagMap{"letter": {"a", "b"}}},
Filter{Kinds: IntList{4, 5}, Tags: TagMap{"letter": {"b", "a"}}},
Filter{Kinds: []int{4, 5}, Tags: TagMap{"letter": {"a", "b"}}},
Filter{Kinds: []int{4, 5}, Tags: TagMap{"letter": {"b", "a"}}},
) {
t.Error("kind+tags filters should be equal")
}
@ -81,24 +83,24 @@ func TestFilterEquality(t *testing.T) {
tm := time.Now()
if !FilterEqual(
Filter{
Kinds: IntList{4, 5},
Kinds: []int{4, 5},
Tags: TagMap{"letter": {"a", "b"}, "fruit": {"banana"}},
Since: &tm,
IDs: StringList{"aaaa", "bbbb"},
IDs: []string{"aaaa", "bbbb"},
},
Filter{
Kinds: IntList{5, 4},
Kinds: []int{5, 4},
Tags: TagMap{"letter": {"a", "b"}, "fruit": {"banana"}},
Since: &tm,
IDs: StringList{"aaaa", "bbbb"},
IDs: []string{"aaaa", "bbbb"},
},
) {
t.Error("kind+2tags+since+ids filters should be equal")
}
if FilterEqual(
Filter{Kinds: IntList{1, 4, 5}},
Filter{Kinds: IntList{4, 5, 6}},
Filter{Kinds: []int{1, 4, 5}},
Filter{Kinds: []int{4, 5, 6}},
) {
t.Error("kinds filters shouldn't be equal")
}

1
go.mod
View File

@ -10,6 +10,7 @@ require (
github.com/tyler-smith/go-bip32 v1.0.0
github.com/tyler-smith/go-bip39 v1.1.0
github.com/valyala/fastjson v1.6.3
golang.org/x/exp v0.0.0-20221106115401-f9659909a136
)
require (

2
go.sum
View File

@ -34,6 +34,8 @@ golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20221106115401-f9659909a136 h1:Fq7F/w7MAa1KJ5bt2aJ62ihqp9HDcRuyILskkpIAurw=
golang.org/x/exp v0.0.0-20221106115401-f9659909a136/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -2,12 +2,11 @@ package nostr
import (
"strings"
"golang.org/x/exp/constraints"
)
type StringList []string
type IntList []int
func (as StringList) Equals(bs StringList) bool {
func Similar[E constraints.Ordered](as, bs []E) bool {
if len(as) != len(bs) {
return false
}
@ -28,37 +27,7 @@ func (as StringList) Equals(bs StringList) bool {
return true
}
func (as IntList) Equals(bs IntList) bool {
if len(as) != len(bs) {
return false
}
for _, a := range as {
for _, b := range bs {
if b == a {
goto next
}
}
// didn't find a B that corresponded to the current A
return false
next:
continue
}
return true
}
func (haystack StringList) Contains(needle string) bool {
for _, hay := range haystack {
if hay == needle {
return true
}
}
return false
}
func (haystack StringList) ContainsPrefixOf(needle string) bool {
func ContainsPrefixOf(haystack []string, needle string) bool {
for _, hay := range haystack {
if strings.HasPrefix(needle, hay) {
return true
@ -66,12 +35,3 @@ func (haystack StringList) ContainsPrefixOf(needle string) bool {
}
return false
}
func (haystack IntList) Contains(needle int) bool {
for _, hay := range haystack {
if hay == needle {
return true
}
}
return false
}