mirror of
https://github.com/diamondburned/arikawa.git
synced 2025-09-04 12:47:54 +00:00
81 lines
2.4 KiB
Go
81 lines
2.4 KiB
Go
package kvdriver
|
|
|
|
import "strings"
|
|
|
|
// BasicDatabase defines a flat key-value database API. It is useful for
|
|
// key-value databases that don't support nesting, such as BadgerDB. Most users
|
|
// should use WrapBasicDatabase to wrap the BasicDatabase and create a full
|
|
// Database.
|
|
type BasicDatabase interface {
|
|
// Get works the same as Database.
|
|
Get(key string, v interface{}) error
|
|
// Set works the same as Database.
|
|
Set(key string, v interface{}) error
|
|
// Each iterates over each key. The database must allow calling Get inside
|
|
// the fn callback.
|
|
Each(fn func(k string) error) error
|
|
// EachIsOrdered works the same as Database.
|
|
EachIsOrdered() bool
|
|
}
|
|
|
|
type wrappedBasicDatabase struct {
|
|
BasicDatabase
|
|
// Delimiter is the default delimiter byte to use. The given keys will be
|
|
// sanitized of this delimiter. The default is a null byte.
|
|
delimiter string
|
|
// state
|
|
prefix string
|
|
}
|
|
|
|
var _ Database = (*wrappedBasicDatabase)(nil)
|
|
|
|
// WrapBasicDatabase wraps the given basic database to provide an emulated
|
|
// nested database. If no delimiter is given, then a single null byte is used.
|
|
func WrapBasicDatabase(basic BasicDatabase, delimiter ...byte) Database {
|
|
return wrapBasicDatabase(basic, delimiter)
|
|
}
|
|
|
|
func wrapBasicDatabase(basic BasicDatabase, delimiter []byte) wrappedBasicDatabase {
|
|
if len(delimiter) == 0 {
|
|
delimiter = []byte{0}
|
|
}
|
|
|
|
return wrappedBasicDatabase{
|
|
BasicDatabase: basic,
|
|
delimiter: string(delimiter),
|
|
}
|
|
}
|
|
|
|
func (b wrappedBasicDatabase) EachIsOrdered() bool {
|
|
return b.BasicDatabase.EachIsOrdered()
|
|
}
|
|
|
|
// Bucket returns a copy of wrappedBasicDatabase with a new prefix.
|
|
func (b wrappedBasicDatabase) Bucket(keys ...string) (Database, error) {
|
|
b.prefix += strings.Join(keys, b.delimiter) + b.delimiter
|
|
return b, nil
|
|
}
|
|
|
|
// Get gets the given key into v.
|
|
func (b wrappedBasicDatabase) Get(key string, v interface{}) error {
|
|
return b.BasicDatabase.Get(b.prefix+key, v)
|
|
}
|
|
|
|
// Sets sets the given key into v.
|
|
func (b wrappedBasicDatabase) Set(key string, v interface{}) error {
|
|
return b.BasicDatabase.Set(b.prefix+key, v)
|
|
}
|
|
|
|
// Each wraps around the BasicDatabase by using its key-only Each API.
|
|
func (b wrappedBasicDatabase) Each(tmp interface{}, fn func(k string) error) error {
|
|
return b.BasicDatabase.Each(func(k string) error {
|
|
key := strings.TrimPrefix(k, b.prefix)
|
|
if strings.Contains(key, b.delimiter) {
|
|
// Skip, since is nested bucket.
|
|
return nil
|
|
}
|
|
|
|
return b.BasicDatabase.Get(k, tmp)
|
|
})
|
|
}
|