Files
crowsnest/internal/data/FileDatastore.go

127 lines
3.4 KiB
Go

package data
import (
"os"
"maps"
"errors"
"encoding/json"
)
type FileDatastore struct {
/* A very simple datastructure, implementing the IDatastore interface. It
* uses a simple text file to the data as json. */
path string
}
func NewFileDatastore(path string) (*FileDatastore, error) {
/* Creates a new FileDatastore object, creating the storage file in the
* process. */
fds := &FileDatastore{ path: path }
if _, err := fds.readMapObj(); err != nil {
if err := fds.writeMapObj(make(map[string]string)); err != nil { return nil, err }
}
return fds, nil
}
func (fds *FileDatastore) readMapObj() (map[string]string, error) {
/* Read the contents of the storage file and convert to a map object. May
* throw an error, if the file does not exit or the file content can not be
* converted. */
dat, err := os.ReadFile(fds.path)
if err != nil { return nil, err }
var mapobj map[string]string
err = json.Unmarshal(dat, &mapobj)
if err != nil { return nil, err }
return mapobj, nil
}
func (fds *FileDatastore) writeMapObj(m map[string]string) error {
/* Write the map object to the storage file. Will overwrite the content of
* the file. May throw an error, if the file cannot be created or written
* to. */
file, err := os.Create(fds.path)
if err != nil { return err }
defer file.Close()
encoder := json.NewEncoder(file)
if err := encoder.Encode(m); err != nil { return err }
return nil
}
// --- implement IDatastore interface ---
func (fds *FileDatastore) Set(key string, val string) error {
/* Sets the key value pair given, overwriting if the key already exists.
* May through an error if the file cannot be opened or the contents cannot
* be decoded correctly. */
m, err := fds.readMapObj()
if err != nil { return err }
m[key] = val
err = fds.writeMapObj(m)
if err != nil { return err }
return nil
}
func (fds *FileDatastore) KeyExists(key string) (bool, error) {
/* Check if for the given key a entry does exit. May through an error if
* the file cannot be opened or the contents cannot be decoded correctly. */
m, err := fds.readMapObj()
if err != nil { return false, err }
_, ok := m[key]
return ok, nil
}
func (fds *FileDatastore) Get(key string) (string, error) {
/* Gets the value for the given key. May through an error if the key does
* not exit, the file cannot be opened or the contents cannot be decoded
* correctly. */
m, err := fds.readMapObj()
if err != nil { return "", err }
val, ok := m[key]
if !ok { return "", errors.New("key not found") }
return val, nil
}
func (fds *FileDatastore) GetAll() (map[string]string, error) {
/* Gets all the key value pairs from the file and returns them as a map
* object. May through an error if the file cannot be opened or the contents
* cannot be decoded correctly. */
return fds.readMapObj()
}
func (fds *FileDatastore) GetAllKeys() (map[string]bool, error) {
/* Gets all the key the file and returns them as a map object. May through
* an error if the file cannot be opened or the contents cannot be decoded
* correctly. */
m, err := fds.readMapObj()
if err != nil { return nil, err }
out := make(map[string]bool)
for key := range maps.Keys(m) {
out[key] = true
}
return out, nil
}