Skip to content

Commit

Permalink
feat(examples): add p/demo/squid
Browse files Browse the repository at this point in the history
  • Loading branch information
thehowl committed Nov 16, 2023
1 parent 7d66398 commit 2144223
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
36 changes: 36 additions & 0 deletions examples/gno.land/p/demo/squid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# squid

```
package squid // import "gno.land/p/demo/squid"
Package squid provides a simple way to have sequential IDs which will be ordered
correctly when inserted in an AVL tree.
Sample usage:
var id squid.ID
var users avl.Tree
func NewUser() {
users.Set(id.Next().Binary(), &User{ ... })
}
TYPES
type ID uint64
An ID is a simple sequential ID generator.
func FromBinary(b string) (ID, bool)
FromBinary creates a new ID from the given string.
func (i ID) Binary() string
Binary returns a big-endian binary representation of the ID, suitable to be
used as an AVL key.
func (i *ID) Next() ID
Next advances the ID i. It will panic if increasing ID would overflow.
func (i *ID) TryNext() (ID, bool)
TryNext increases i by 1 and returns its value. It returns true if
successful, or false if the increment would result in an overflow.
```
1 change: 1 addition & 0 deletions examples/gno.land/p/demo/squid/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/p/demo/squid
57 changes: 57 additions & 0 deletions examples/gno.land/p/demo/squid/squid.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Package squid provides a simple way to have sequential IDs which will be
// ordered correctly when inserted in an AVL tree.
//
// Sample usage:
//
// var id squid.ID
// var users avl.Tree
//
// func NewUser() {
// users.Set(id.Next().Binary(), &User{ ... })
// }
package squid

import "encoding/binary"

// An ID is a simple sequential ID generator.
type ID uint64

// Next advances the ID i.
// It will panic if increasing ID would overflow.
func (i *ID) Next() ID {
next, ok := i.TryNext()
if !ok {
panic("squid: next ID overflows uint64")
}
return next
}

const maxUint64 uint64 = 1<<64 - 1

// TryNext increases i by 1 and returns its value.
// It returns true if successful, or false if the increment would result in
// an overflow.
func (i *ID) TryNext() (ID, bool) {
if *i == maxUint64 {
// Addition will overflow.
return 0, false
}
*i++
return *i, true
}

// Binary returns a big-endian binary representation of the ID,
// suitable to be used as an AVL key.
func (i ID) Binary() string {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
return string(buf)
}

// FromBinary creates a new ID from the given string.
func FromBinary(b string) (ID, bool) {
if len(b) != 8 {
return 0, false
}
return ID(binary.BigEndian.Uint64([]byte(b))), true
}
43 changes: 43 additions & 0 deletions examples/gno.land/p/demo/squid/squid_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package squid

import (
"strings"
"testing"
"fmt"
)

func TestID(t *testing.T) {
var i ID

for j := 0; j < 100; j++ {
i.Next()
}
if i != 100 {
t.Fatalf("invalid: wanted %d got %d", 100, i)
}
}

func TestID_Overflow(t *testing.T) {
i := ID(maxUint64)

defer func() {
err := recover()
if !strings.Contains(fmt.Sprint(err), "next ID overflows") {
t.Errorf("did not overflow")
}
}()

i.Next()
}

func TestID_Binary(t *testing.T) {
var i ID
prev := i.Binary()

for j := 0; j < 1000; j++ {
cur := i.Next().Binary()
if cur <= prev {
t.Fatalf("cur %x <= prev %x", cur, prev)
}
}
}

0 comments on commit 2144223

Please sign in to comment.