85 lines
1.4 KiB
Go
85 lines
1.4 KiB
Go
package repo
|
|
|
|
import (
|
|
"encoding"
|
|
"errors"
|
|
|
|
e "github.com/iliadenisov/galaxy/internal/error"
|
|
"github.com/iliadenisov/galaxy/internal/repo/fs"
|
|
)
|
|
|
|
func NewStorageError(err error) error {
|
|
return e.NewRepoError(err)
|
|
}
|
|
|
|
func NewGameNotInitializedError() error {
|
|
return e.NewGameNotInitializedError()
|
|
}
|
|
|
|
func NewStateError(msg string) error {
|
|
return e.NewGameStateError(msg)
|
|
}
|
|
|
|
type Storage interface {
|
|
Lock() (func() error, error)
|
|
Exists(string) (bool, error)
|
|
Write(string, encoding.BinaryMarshaler) error
|
|
Read(string, encoding.BinaryUnmarshaler) error
|
|
ReadSafe(string, encoding.BinaryUnmarshaler) error
|
|
}
|
|
|
|
type repo struct {
|
|
s Storage
|
|
release func() error
|
|
}
|
|
|
|
func NewRepo(s Storage) (*repo, error) {
|
|
r := &repo{
|
|
s: s,
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func NewFileRepo(path string) (*repo, error) {
|
|
s, err := fs.NewFileStorage(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return NewRepo(s)
|
|
}
|
|
|
|
func (r *repo) Lock() (err error) {
|
|
if r.s == nil {
|
|
return errors.New("storage is closed")
|
|
}
|
|
if r.release != nil {
|
|
return errors.New("storage already locked")
|
|
}
|
|
r.release, err = r.s.Lock()
|
|
if err != nil {
|
|
r.close()
|
|
return
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *repo) Release() (err error) {
|
|
if r.s == nil {
|
|
return errors.New("storage is closed")
|
|
}
|
|
if r.release == nil {
|
|
return errors.New("storage was never locked")
|
|
}
|
|
err = r.release()
|
|
if err != nil {
|
|
return
|
|
}
|
|
r.close()
|
|
return nil
|
|
}
|
|
|
|
func (r *repo) close() {
|
|
r.release = nil
|
|
r.s = nil
|
|
}
|