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 }