101 lines
1.8 KiB
Go
101 lines
1.8 KiB
Go
package ocean
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path"
|
|
"sync"
|
|
)
|
|
|
|
type Collection[T any] interface {
|
|
All() <-chan T
|
|
Delete(key string)
|
|
Exists(key string) bool
|
|
Get(key string) (value T, ok bool)
|
|
Set(key string, value T)
|
|
}
|
|
|
|
// collection is a hash map of homogeneous data.
|
|
type collection[T any] struct {
|
|
data sync.Map
|
|
name string
|
|
directory string
|
|
}
|
|
|
|
// NewCollection creates a new collection with the given name.
|
|
func NewCollection[T any](namespace string, name string) (*collection[T], error) {
|
|
home, err := os.UserHomeDir()
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
directory := path.Join(home, ".ocean", namespace, name)
|
|
err = os.MkdirAll(directory, 0700)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c := &collection[T]{
|
|
name: name,
|
|
directory: directory,
|
|
}
|
|
|
|
return c, err
|
|
}
|
|
|
|
// Get returns the value for the given key.
|
|
func (c *collection[T]) Get(key string) (T, bool) {
|
|
value, exists := c.data.Load(key)
|
|
return value.(T), exists
|
|
}
|
|
|
|
// Set sets the value for the given key.
|
|
func (c *collection[T]) Set(key string, value T) {
|
|
c.data.Store(key, value)
|
|
|
|
fileName := path.Join(c.directory, key+".json")
|
|
file, err := os.Create(fileName)
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
encoder := json.NewEncoder(file)
|
|
encoder.Encode(value)
|
|
|
|
err = file.Close()
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// Delete deletes a key from the collection.
|
|
func (c *collection[T]) Delete(key string) {
|
|
c.data.Delete(key)
|
|
}
|
|
|
|
// Exists returns whether or not the key exists.
|
|
func (c *collection[T]) Exists(key string) bool {
|
|
_, exists := c.data.Load(key)
|
|
return exists
|
|
}
|
|
|
|
// All returns a channel of all objects in the collection.
|
|
func (c *collection[T]) All() <-chan T {
|
|
channel := make(chan T)
|
|
|
|
go func() {
|
|
c.data.Range(func(key, value any) bool {
|
|
channel <- value.(T)
|
|
return true
|
|
})
|
|
|
|
close(channel)
|
|
}()
|
|
|
|
return channel
|
|
}
|