diff --git a/go.mod b/go.mod index 3d03923..83c19a2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/nbd-wtf/go-nostr -go 1.23.0 +go 1.23.1 require ( github.com/bluekeyes/go-gitdiff v0.7.1 @@ -24,10 +24,10 @@ require ( github.com/tursodatabase/go-libsql v0.0.0-20240916111504-922dfa87e1e6 github.com/tyler-smith/go-bip32 v1.0.0 github.com/tyler-smith/go-bip39 v1.1.0 - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.28.0 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/net v0.21.0 - golang.org/x/text v0.18.0 + golang.org/x/text v0.19.0 modernc.org/sqlite v1.33.1 ) @@ -57,7 +57,7 @@ require ( github.com/tetratelabs/wazero v1.8.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect - golang.org/x/sys v0.25.0 // indirect + golang.org/x/sys v0.26.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect modernc.org/libc v1.55.3 // indirect diff --git a/go.sum b/go.sum index 972fbdd..940ce7f 100644 --- a/go.sum +++ b/go.sum @@ -177,8 +177,8 @@ golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= @@ -203,13 +203,13 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= diff --git a/tag_test.go b/tag_test.go index ddb00d0..8edff85 100644 --- a/tag_test.go +++ b/tag_test.go @@ -21,8 +21,18 @@ func TestTagHelpers(t *testing.T) { assert.NotNil(t, tags.GetFirst([]string{"p", "abcdef", ""}), "failed to get with existing prefix (blank last string)") assert.Equal(t, "ffffff", (*(tags.GetLast([]string{"e"})))[1], "failed to get last") assert.Equal(t, 2, len(tags.GetAll([]string{"e", ""})), "failed to get all") + c := make(Tags, 0, 2) + for _, tag := range tags.All([]string{"e", ""}) { + c = append(c, tag) + } + assert.Equal(t, tags.GetAll([]string{"e", ""}), c) assert.Equal(t, 5, len(tags.AppendUnique(Tag{"e", "ffffff"})), "append unique changed the array size when existed") assert.Equal(t, 6, len(tags.AppendUnique(Tag{"e", "bbbbbb"})), "append unique failed to append when didn't exist") assert.Equal(t, "ffffff", tags.AppendUnique(Tag{"e", "eeeeee"})[4][1], "append unique changed the order") assert.Equal(t, "eeeeee", tags.AppendUnique(Tag{"e", "eeeeee"})[3][1], "append unique changed the order") + + filtered := tags.FilterOut([]string{"e"}) + tags.FilterOutInPlace([]string{"e"}) + assert.ElementsMatch(t, filtered, tags) + assert.Len(t, filtered, 3) } diff --git a/tags.go b/tags.go index c02a95e..1cf5f2d 100644 --- a/tags.go +++ b/tags.go @@ -3,9 +3,9 @@ package nostr import ( "encoding/json" "errors" - "strings" - + "iter" "slices" + "strings" ) type Tag []string @@ -103,7 +103,20 @@ func (tags Tags) GetAll(tagPrefix []string) Tags { return result } -// FilterOut removes all tags that match the prefix, see [Tag.StartsWith] +// All returns an iterator for all the tags that match the prefix, see [Tag.StartsWith] +func (tags Tags) All(tagPrefix []string) iter.Seq2[int, Tag] { + return func(yield func(int, Tag) bool) { + for i, v := range tags { + if v.StartsWith(tagPrefix) { + if !yield(i, v) { + break + } + } + } + } +} + +// FilterOut returns a new slice with only the elements that match the prefix, see [Tag.StartsWith] func (tags Tags) FilterOut(tagPrefix []string) Tags { filtered := make(Tags, 0, len(tags)) for _, v := range tags { @@ -114,6 +127,20 @@ func (tags Tags) FilterOut(tagPrefix []string) Tags { return filtered } +// FilterOutInPlace removes all tags that match the prefix, but potentially reorders the tags in unpredictable ways, see [Tag.StartsWith] +func (tags *Tags) FilterOutInPlace(tagPrefix []string) { + for i := 0; i < len(*tags); i++ { + tag := (*tags)[i] + if tag.StartsWith(tagPrefix) { + // remove this by swapping the last tag into this place + last := len(*tags) - 1 + (*tags)[i] = (*tags)[last] + *tags = (*tags)[0:last] + i-- // this is so we can match this just swapped item in the next iteration + } + } +} + // AppendUnique appends a tag if it doesn't exist yet, otherwise does nothing. // the uniqueness comparison is done based only on the first 2 elements of the tag. func (tags Tags) AppendUnique(tag Tag) Tags {