Skip to content

Commit

Permalink
Add zset value type (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
murex971 committed Aug 9, 2020
1 parent f0043e9 commit 563cbc2
Show file tree
Hide file tree
Showing 14 changed files with 1,637 additions and 0 deletions.
2 changes: 2 additions & 0 deletions go.mod
@@ -1,3 +1,5 @@
module github.com/sdslabs/kiwi

go 1.14

require github.com/wangjia184/sortedset v0.0.0-20200422044937-080872f546ba
2 changes: 2 additions & 0 deletions go.sum
@@ -0,0 +1,2 @@
github.com/wangjia184/sortedset v0.0.0-20200422044937-080872f546ba h1:jrGJzVnPfTOo7yb0qXeXc6biQFlDjzp4evucTpZZFTc=
github.com/wangjia184/sortedset v0.0.0-20200422044937-080872f546ba/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE=
12 changes: 12 additions & 0 deletions stdkiwi/store.go
Expand Up @@ -101,6 +101,18 @@ func (s *Store) Hash(key string) *Hash {
}
}

// Zset returns a "Zset" with the key set as "key".
//
// This does not verify if the key and value type pair is correct.
// If this does not work, "Do" will eventually throw an error.
// To avoid this use "GuardE" method or "Guard" if schema is pre-defined.
func (s *Store) Zset(key string) *Zset {
return &Zset{
store: s,
key: key,
}
}

// Value can be used to access the methods for standard value types.
type Value interface {
// Guard should panic if the key does not correspond to the correct type.
Expand Down
131 changes: 131 additions & 0 deletions stdkiwi/zset.go
@@ -0,0 +1,131 @@
// Copyright (c) 2020 SDSLabs
// Use of this source code is governed by an MIT license
// details of which can be found in the LICENSE file.

package stdkiwi

import "github.com/sdslabs/kiwi/values/zset"

// Zset implements methods for zset value type.
type Zset struct {
store *Store
key string
}

// Guard guards the keys with values of str type.
func (z *Zset) Guard() {
if err := z.GuardE(); err != nil {
panic(err)
}
}

// GuardE is same as Guard but does not panic, instead returns the error.
func (z *Zset) GuardE() error { return z.store.guardValueE(zset.Type, z.key) }

// Insert inserts the elements to the zset.
func (z *Zset) Insert(elements ...string) error {
if len(elements) == 0 {
return nil
}

ifaces := make([]interface{}, len(elements))
for i := range elements {
ifaces[i] = elements[i]
}

if _, err := z.store.Do(z.key, zset.Insert, ifaces...); err != nil {
return err
}

return nil
}

// Remove removes the elements from the zset.
func (z *Zset) Remove(elements ...string) error {
if len(elements) == 0 {
return nil
}

ifaces := make([]interface{}, len(elements))
for i := range elements {
ifaces[i] = elements[i]
}

if _, err := z.store.Do(z.key, zset.Remove, ifaces...); err != nil {
return err
}

return nil
}

// Increment increment the score of element of the zset.
func (z *Zset) Increment(element string, score int) error {
if _, err := z.store.Do(z.key, zset.Increment, element, score); err != nil {
return err
}

return nil
}

// Get gets the score of element from the zset.
func (z *Zset) Get(element string) (int, error) {
v, err := z.store.Do(z.key, zset.Get, element)
if err != nil {
return -1, err
}

val, ok := v.(int)
if !ok {
return -1, newTypeErr(val, v)
}

return val, nil
}

// Len gets the length of the zset.
func (z *Zset) Len() (int, error) {
v, err := z.store.Do(z.key, zset.Len)
if err != nil {
return 0, err
}

length, ok := v.(int)
if !ok {
return 0, newTypeErr(length, v)
}

return length, nil
}

// PeekMax gets the element with highest score from the zset.
func (z *Zset) PeekMax() (string, error) {
v, err := z.store.Do(z.key, zset.PeekMax)
if err != nil {
return "", err
}

val, ok := v.(string)
if !ok {
return "", newTypeErr(val, v)
}

return val, nil
}

// PeekMin gets the element with minimum score from the zset.
func (z *Zset) PeekMin() (string, error) {
v, err := z.store.Do(z.key, zset.PeekMin)
if err != nil {
return "", err
}

val, ok := v.(string)
if !ok {
return "", newTypeErr(val, v)
}

return val, nil
}

// Interface guard.
var _ Value = (*Set)(nil)
76 changes: 76 additions & 0 deletions stdkiwi/zset_test.go
@@ -0,0 +1,76 @@
// Copyright (c) 2020 SDSLabs
// Use of this source code is governed by an MIT license
// details of which can be found in the LICENSE file.

package stdkiwi

import (
"testing"

"github.com/sdslabs/kiwi/values/zset"
)

func TestZSet(t *testing.T) {
store := newTestStore(t, zset.Type)
s := store.Zset(testKey)

// check that it does not panic
s.Guard()

// and the same should work with GuardE as well
if err := s.GuardE(); err != nil {
t.Errorf("GuardE threw an error for default testKey: %v", err)
}

vals := []string{"a", "b", "c", "d", "e", "f", "g", "h"}

if err := s.Insert(vals...); err != nil {
t.Errorf("could not Insert: %v", err)
}

length, err := s.Len()
if err != nil {
t.Errorf("could not Len: %v", err)
}

if length != len(vals) {
t.Errorf("expected length of zset: %d; got %d", len(vals), length)
}

// updating score to some non zero values.

if err = s.Increment("a", 5); err != nil {
t.Errorf("could not increment: %v", err)
}

if err = s.Increment("f", -5); err != nil {
t.Errorf("could not Increment: %v", err)
}

score, err := s.Get("b")
if err != nil {
t.Errorf("could not Get: %v", err)
}

if score != 0 {
t.Errorf("expected score: %d; got: %d", 0, score)
}

maxstr, err := s.PeekMax()
if err != nil {
t.Errorf("could not PeekMax: %v", err)
}

if maxstr != "a" {
t.Errorf("expected element: %q; got: %q", "a", maxstr)
}

minstr, err := s.PeekMin()
if err != nil {
t.Errorf("could not PeekMin: %v", err)
}

if minstr != "f" {
t.Errorf("expected element: %q; got: %q", "f", minstr)
}
}
7 changes: 7 additions & 0 deletions values/zset/doc.go
@@ -0,0 +1,7 @@
// Copyright (c) 2020 SDSLabs
// Use of this source code is governed by an MIT license
// details of which can be found in the LICENSE file.

// Package zset implements a kiwi.Value which can store a set
// with each element having score.
package zset

0 comments on commit 563cbc2

Please sign in to comment.