Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: In r/demo/users, add ListUsersByPrefix #1708

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions examples/gno.land/p/demo/avlhelpers/avlhelpers.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package avlhelpers

import (
"gno.land/p/demo/avl"
)

// Get a list of keys starting from the given prefix. Limit the
// number of results to maxResults.
// The prefix and keys are treated as byte strings, ignoring possible multi-byte Unicode runes.
func ListByteStringKeysByPrefix(tree avl.Tree, prefix string, maxResults int) []string {
jefft0 marked this conversation as resolved.
Show resolved Hide resolved
end := ""
n := len(prefix)
// To make the end of the search, increment the final character ASCII by one.
for n > 0 {
if ascii := int(prefix[n-1]); ascii < 0xff {
end = prefix[0:n-1] + string(ascii+1)
break
}
jefft0 marked this conversation as resolved.
Show resolved Hide resolved

// The last character is 0xff. Try the previous character.
n--
}

result := []string{}
tree.Iterate(prefix, end, func(key string, value interface{}) bool {
result = append(result, key)
if len(result) >= maxResults {
return true
}
return false
})
return result
}
3 changes: 3 additions & 0 deletions examples/gno.land/p/demo/avlhelpers/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module gno.land/p/demo/avlhelpers

require gno.land/p/demo/avl v0.0.0-latest
91 changes: 91 additions & 0 deletions examples/gno.land/p/demo/avlhelpers/z_0_filetest.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// PKGPATH: gno.land/r/test
package test

import (
"encoding/hex"

"gno.land/p/demo/avl"
"gno.land/p/demo/avlhelpers"
"gno.land/p/demo/ufmt"
)

func main() {
tree := avl.Tree{}

{
// Empty tree.
matches := avlhelpers.ListByteStringKeysByPrefix(tree, "", 10)
println(ufmt.Sprintf("# matches: %d", len(matches)))
}

tree.Set("alice", "")
tree.Set("andy", "")
tree.Set("bob", "")

{
// Match only alice.
matches := avlhelpers.ListByteStringKeysByPrefix(tree, "al", 10)
println(ufmt.Sprintf("# matches: %d", len(matches)))
println("match: " + matches[0])
}

{
// Match alice and andy.
matches := avlhelpers.ListByteStringKeysByPrefix(tree, "a", 10)
println(ufmt.Sprintf("# matches: %d", len(matches)))
println("match: " + matches[0])
println("match: " + matches[1])
}

{
// Match alice and andy limited to 1.
matches := avlhelpers.ListByteStringKeysByPrefix(tree, "a", 1)
println(ufmt.Sprintf("# matches: %d", len(matches)))
println("match: " + matches[0])
}

tree = avl.Tree{}
tree.Set("a\xff", "")
tree.Set("a\xff\xff", "")
tree.Set("b", "")
tree.Set("\xff\xff\x00", "")

{
// Match only "a\xff\xff".
matches := avlhelpers.ListByteStringKeysByPrefix(tree, "a\xff\xff", 10)
println(ufmt.Sprintf("# matches: %d", len(matches)))
println(ufmt.Sprintf("match: %s", hex.EncodeToString([]byte(matches[0]))))
}

{
// Match "a\xff" and "a\xff\xff".
matches := avlhelpers.ListByteStringKeysByPrefix(tree, "a\xff", 10)
println(ufmt.Sprintf("# matches: %d", len(matches)))
println(ufmt.Sprintf("match: %s", hex.EncodeToString([]byte(matches[0]))))
println(ufmt.Sprintf("match: %s", hex.EncodeToString([]byte(matches[1]))))
}

{
// Edge case: Match only "\xff\xff\x00".
matches := avlhelpers.ListByteStringKeysByPrefix(tree, "\xff\xff", 10)
println(ufmt.Sprintf("# matches: %d", len(matches)))
println(ufmt.Sprintf("match: %s", hex.EncodeToString([]byte(matches[0]))))
}
}

// Output:
// # matches: 0
// # matches: 1
// match: alice
// # matches: 2
// match: alice
// match: andy
// # matches: 1
// match: alice
// # matches: 1
// match: 61ffff
// # matches: 2
// match: 61ff
// match: 61ffff
// # matches: 1
// match: ffff00
1 change: 1 addition & 0 deletions examples/gno.land/r/demo/users/gno.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ module gno.land/r/demo/users

require (
gno.land/p/demo/avl v0.0.0-latest
gno.land/p/demo/avlhelpers v0.0.0-latest
gno.land/p/demo/users v0.0.0-latest
)
7 changes: 7 additions & 0 deletions examples/gno.land/r/demo/users/users.gno
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"

"gno.land/p/demo/avl"
"gno.land/p/demo/avlhelpers"
"gno.land/p/demo/users"
)

Expand Down Expand Up @@ -255,6 +256,12 @@ func GetUserByAddressOrName(input users.AddressOrName) *users.User {
return GetUserByAddress(std.Address(input))
}

// Get a list of user names starting from the given prefix. Limit the
// number of results to maxResults. (This can be used for a name search tool.)
func ListUsersByPrefix(prefix string, maxResults int) []string {
jefft0 marked this conversation as resolved.
Show resolved Hide resolved
return avlhelpers.ListByteStringKeysByPrefix(name2User, prefix, maxResults)
}

func Resolve(input users.AddressOrName) std.Address {
name, isName := input.GetName()
if !isName {
Expand Down
49 changes: 49 additions & 0 deletions examples/gno.land/r/demo/users/z_12_filetest.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package main

// SEND: 200000000ugnot

import (
"strconv"

"gno.land/r/demo/users"
)

func main() {
users.Register("", "alicia", "my profile")

{
// Normal usage
names := users.ListUsersByPrefix("a", 1)
println("# names: " + strconv.Itoa(len(names)))
println("name: " + names[0])
}

{
// Empty prefix: match all
names := users.ListUsersByPrefix("", 1)
println("# names: " + strconv.Itoa(len(names)))
println("name: " + names[0])
}

{
// The prefix is before "alicia"
names := users.ListUsersByPrefix("alich", 1)
println("# names: " + strconv.Itoa(len(names)))
}

{
// The prefix is after the last name
names := users.ListUsersByPrefix("y", 10)
println("# names: " + strconv.Itoa(len(names)))
}

// More tests are in p/demo/avlhelpers
}

// Output:
// # names: 1
// name: alicia
// # names: 1
// name: alicia
// # names: 0
// # names: 0
Loading