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 }