fs use binary (um)marshaler

This commit is contained in:
Ilia Denisov
2025-09-23 22:02:21 +03:00
parent 4d733ae741
commit c777ba91dd
4 changed files with 51 additions and 10 deletions
+24 -5
View File
@@ -1,6 +1,7 @@
package fs package fs
import ( import (
"encoding"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
@@ -74,7 +75,11 @@ func (f *fs) Lock() (func() error, error) {
return unlock, nil return unlock, nil
} }
func (f *fs) Write(path string, data []byte) error { func (f *fs) Write(path string, v encoding.BinaryMarshaler) error {
if v == nil {
return errors.New("cant't marshal from nil object")
}
if f.lock == nil { if f.lock == nil {
return errors.New("lock must be acquired before write") return errors.New("lock must be acquired before write")
} }
@@ -84,6 +89,11 @@ func (f *fs) Write(path string, data []byte) error {
return errors.New("can't write to the lock file") return errors.New("can't write to the lock file")
} }
data, err := v.MarshalBinary()
if err != nil {
return fmt.Errorf("marshal data: %s", err)
}
targetDir := filepath.Dir(targetFilePath) targetDir := filepath.Dir(targetFilePath)
if targetDir != f.root { if targetDir != f.root {
ok, err := dirExists(targetDir) ok, err := dirExists(targetDir)
@@ -146,17 +156,26 @@ func (f *fs) Write(path string, data []byte) error {
return nil return nil
} }
func (f *fs) Read(path string) ([]byte, error) { func (f *fs) Read(path string, v encoding.BinaryUnmarshaler) error {
if v == nil {
return errors.New("can't unmarshal to a nil object")
}
if f.lock != nil { if f.lock != nil {
return nil, errors.New("lock must be released before read") return errors.New("lock must be released before read")
} }
targetFilePath := filepath.Join(f.root, path) targetFilePath := filepath.Join(f.root, path)
if targetFilePath == f.lockFilePath() { if targetFilePath == f.lockFilePath() {
return nil, errors.New("can't read from the lock file") return errors.New("can't read from the lock file")
} }
return os.ReadFile(targetFilePath) data, err := os.ReadFile(targetFilePath)
if err != nil {
return fmt.Errorf("reading data file: %s", err)
}
return v.UnmarshalBinary(data)
} }
func (f *fs) lockFilePath() string { func (f *fs) lockFilePath() string {
+6 -3
View File
@@ -58,7 +58,8 @@ func TestWrite(t *testing.T) {
{path: "/" + dirName, err: "wrong type"}, {path: "/" + dirName, err: "wrong type"},
} { } {
t.Run(tc.path, func(t *testing.T) { t.Run(tc.path, func(t *testing.T) {
err = fs.Write(tc.path, []byte{0, 1, 2, 3}) sd := &sampleData{[]byte{0, 1, 2, 3}}
err = fs.Write(tc.path, sd)
if tc.err == "" { if tc.err == "" {
if err != nil { if err != nil {
assert.Fail(t, "not expecting an error", "write to file %s: %s", tc.path, err) assert.Fail(t, "not expecting an error", "write to file %s: %s", tc.path, err)
@@ -122,7 +123,8 @@ func TestRead(t *testing.T) {
} }
}() }()
} }
_, err = fs.Read(tc.path) sd := new(sampleData)
err = fs.Read(tc.path, sd)
if tc.err == "" { if tc.err == "" {
if err != nil { if err != nil {
assert.Fail(t, "read: not expecting an error, got: "+err.Error()) assert.Fail(t, "read: not expecting an error, got: "+err.Error())
@@ -147,7 +149,8 @@ func TestWriteErrorWithoutLock(t *testing.T) {
defer cleanup() defer cleanup()
fs, err := NewFileStorage(root) fs, err := NewFileStorage(root)
assert.NoError(t, err, "create file storage") assert.NoError(t, err, "create file storage")
err = fs.Write("some/path", []byte{0, 1, 2, 3}) sd := &sampleData{[]byte{0, 1, 2, 3}}
err = fs.Write("some/path", sd)
assert.Error(t, err, "should return error when no lock acquired") assert.Error(t, err, "should return error when no lock acquired")
assert.True(t, strings.Contains(err.Error(), "lock must be acquired"), "should return missing lock error") assert.True(t, strings.Contains(err.Error(), "lock must be acquired"), "should return missing lock error")
} }
+14
View File
@@ -2,6 +2,7 @@ package fs
import ( import (
"os" "os"
"slices"
"testing" "testing"
) )
@@ -21,3 +22,16 @@ func createWorkDir(t *testing.T) (string, func()) {
} }
} }
} }
type sampleData struct {
data []byte
}
func (sd *sampleData) UnmarshalBinary(data []byte) error {
sd.data = slices.Clone(data)
return nil
}
func (sd sampleData) MarshalBinary() (data []byte, err error) {
return sd.data, nil
}
+7 -2
View File
@@ -1,10 +1,15 @@
package repo package repo
import "github.com/iliadenisov/galaxy/pkg/repo/fs" import (
"encoding"
"github.com/iliadenisov/galaxy/pkg/repo/fs"
)
type Storage interface { type Storage interface {
Lock() (func() error, error) Lock() (func() error, error)
Write(string, []byte) error Write(string, encoding.BinaryMarshaler) error
Read(string, encoding.BinaryUnmarshaler) error
} }
type repo struct { type repo struct {