133 lines
3.6 KiB
Go
133 lines
3.6 KiB
Go
package data
|
|
|
|
import (
|
|
"os"
|
|
"maps"
|
|
"errors"
|
|
"encoding/json"
|
|
)
|
|
|
|
|
|
// A very simple datastructure, implementing the IDatastore interface. It uses
|
|
// a simple text file to the data as json.
|
|
type FileDatastore struct {
|
|
path string
|
|
}
|
|
|
|
// Creates a new FileDatastore object, creating the storage file in the
|
|
// process.
|
|
func NewFileDatastore(path string) (*FileDatastore, error) {
|
|
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
|
|
}
|
|
|
|
// 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.
|
|
func (fds *FileDatastore) readMapObj() (map[string]string, error) {
|
|
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
|
|
}
|
|
|
|
// 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.
|
|
func (fds *FileDatastore) writeMapObj(m map[string]string) error {
|
|
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 ---
|
|
|
|
// 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.
|
|
func (fds *FileDatastore) Set(key string, val string) error {
|
|
m, err := fds.readMapObj()
|
|
if err != nil { return err }
|
|
|
|
m[key] = val
|
|
|
|
err = fds.writeMapObj(m)
|
|
if err != nil { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
// 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.
|
|
func (fds *FileDatastore) KeyExists(key string) (bool, error) {
|
|
m, err := fds.readMapObj()
|
|
if err != nil { return false, err }
|
|
|
|
_, ok := m[key]
|
|
|
|
return ok, nil
|
|
}
|
|
|
|
// 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.
|
|
func (fds *FileDatastore) Get(key string) (string, error) {
|
|
m, err := fds.readMapObj()
|
|
if err != nil { return "", err }
|
|
|
|
val, ok := m[key]
|
|
if !ok { return "", errors.New("key not found") }
|
|
|
|
return val, nil
|
|
}
|
|
|
|
// 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.
|
|
func (fds *FileDatastore) GetAll() (map[string]string, error) {
|
|
return fds.readMapObj()
|
|
}
|
|
|
|
// 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.
|
|
func (fds *FileDatastore) GetAllKeys() (map[string]bool, error) {
|
|
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
|
|
}
|
|
|
|
// Deletes the entry with the given key. May through an error if the file
|
|
// cannot be opened or the contents cannot be decoded or encoded correctly.
|
|
func (fds *FileDatastore) Delete(key string) error {
|
|
m, err := fds.readMapObj()
|
|
if err != nil { return err }
|
|
|
|
delete(m, key)
|
|
|
|
err = fds.writeMapObj(m)
|
|
if err != nil { return err }
|
|
|
|
return nil
|
|
}
|