134 lines
2.2 KiB
Go
134 lines
2.2 KiB
Go
package memory
|
|
|
|
import (
|
|
"s1d3sw1ped/SteamCache2/vfs"
|
|
"s1d3sw1ped/SteamCache2/vfs/vfserror"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Ensure MemoryFS implements VFS.
|
|
var _ vfs.VFS = (*MemoryFS)(nil)
|
|
|
|
// file represents a file in memory.
|
|
type file struct {
|
|
fileinfo *vfs.FileInfo
|
|
data []byte
|
|
}
|
|
|
|
// MemoryFS is a virtual file system that stores files in memory.
|
|
type MemoryFS struct {
|
|
files map[string]*file
|
|
capacity int64
|
|
mu sync.Mutex
|
|
}
|
|
|
|
// New creates a new MemoryFS.
|
|
func New(capacity int64) *MemoryFS {
|
|
return &MemoryFS{
|
|
files: make(map[string]*file),
|
|
capacity: capacity,
|
|
mu: sync.Mutex{},
|
|
}
|
|
}
|
|
|
|
func (m *MemoryFS) Capacity() int64 {
|
|
return m.capacity
|
|
}
|
|
|
|
func (m *MemoryFS) Name() string {
|
|
return "MemoryFS"
|
|
}
|
|
|
|
func (m *MemoryFS) Size() int64 {
|
|
var size int64
|
|
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
for _, v := range m.files {
|
|
size += int64(len(v.data))
|
|
}
|
|
|
|
return size
|
|
}
|
|
|
|
func (m *MemoryFS) Set(key string, src []byte) error {
|
|
if m.capacity > 0 {
|
|
if size := m.Size() + int64(len(src)); size > m.capacity {
|
|
return vfserror.ErrDiskFull
|
|
}
|
|
}
|
|
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
m.files[key] = &file{
|
|
fileinfo: vfs.NewFileInfo(
|
|
key,
|
|
int64(len(src)),
|
|
time.Now(),
|
|
),
|
|
data: make([]byte, len(src)),
|
|
}
|
|
copy(m.files[key].data, src)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MemoryFS) Delete(key string) error {
|
|
_, err := m.Stat(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
delete(m.files, key)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MemoryFS) Get(key string) ([]byte, error) {
|
|
_, err := m.Stat(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
m.files[key].fileinfo.ATime = time.Now()
|
|
dst := make([]byte, len(m.files[key].data))
|
|
copy(dst, m.files[key].data)
|
|
|
|
return dst, nil
|
|
}
|
|
|
|
func (m *MemoryFS) Stat(key string) (*vfs.FileInfo, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
f, ok := m.files[key]
|
|
if !ok {
|
|
return nil, vfserror.ErrNotFound
|
|
}
|
|
|
|
return f.fileinfo, nil
|
|
}
|
|
|
|
func (m *MemoryFS) StatAll() []*vfs.FileInfo {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
// hard copy the file info to prevent modification of the original file info or the other way around
|
|
files := make([]*vfs.FileInfo, 0, len(m.files))
|
|
for _, v := range m.files {
|
|
fi := *v.fileinfo
|
|
files = append(files, &fi)
|
|
}
|
|
|
|
return files
|
|
}
|