oprimized, working

This commit is contained in:
royalcat 2023-12-22 02:15:39 +03:00
parent 2b39afca3b
commit 0350ecba9a
38 changed files with 1809 additions and 826 deletions
src/host/vfs

View file

@ -3,27 +3,27 @@ package vfs
import (
"fmt"
"io/fs"
"path"
"slices"
"strings"
"sync"
)
type ResolveFS struct {
osDir string
osFS *OsFS
rootFS Filesystem
resolver *resolver
}
func NewResolveFS(osDir string, factories map[string]FsFactory) *ResolveFS {
func NewResolveFS(rootFs Filesystem, factories map[string]FsFactory) *ResolveFS {
return &ResolveFS{
osDir: osDir,
osFS: NewOsFs(osDir),
rootFS: rootFs,
resolver: newResolver(factories),
}
}
// Open implements Filesystem.
func (r *ResolveFS) Open(filename string) (File, error) {
fsPath, nestedFs, nestedFsPath, err := r.resolver.resolvePath(filename, r.osFS.Open)
fsPath, nestedFs, nestedFsPath, err := r.resolver.resolvePath(filename, r.rootFS.Open)
if err != nil {
return nil, err
}
@ -31,12 +31,12 @@ func (r *ResolveFS) Open(filename string) (File, error) {
return nestedFs.Open(nestedFsPath)
}
return r.osFS.Open(fsPath)
return r.rootFS.Open(fsPath)
}
// ReadDir implements Filesystem.
func (r *ResolveFS) ReadDir(dir string) (map[string]File, error) {
fsPath, nestedFs, nestedFsPath, err := r.resolver.resolvePath(dir, r.osFS.Open)
func (r *ResolveFS) ReadDir(dir string) ([]fs.DirEntry, error) {
fsPath, nestedFs, nestedFsPath, err := r.resolver.resolvePath(dir, r.rootFS.Open)
if err != nil {
return nil, err
}
@ -44,7 +44,32 @@ func (r *ResolveFS) ReadDir(dir string) (map[string]File, error) {
return nestedFs.ReadDir(nestedFsPath)
}
return r.osFS.ReadDir(fsPath)
entries, err := r.rootFS.ReadDir(fsPath)
if err != nil {
return nil, err
}
out := make([]fs.DirEntry, 0, len(entries))
for _, e := range entries {
if r.resolver.isNestedFs(e.Name()) {
out = append(out, newDirInfo(e.Name()))
} else {
out = append(out, e)
}
}
return out, nil
}
// Stat implements Filesystem.
func (r *ResolveFS) Stat(filename string) (fs.FileInfo, error) {
fsPath, nestedFs, nestedFsPath, err := r.resolver.resolvePath(filename, r.rootFS.Open)
if err != nil {
return nil, err
}
if nestedFs != nil {
return nestedFs.Stat(nestedFsPath)
}
return r.rootFS.Stat(fsPath)
}
var _ Filesystem = &ResolveFS{}
@ -69,8 +94,18 @@ type resolver struct {
type openFile func(path string) (File, error)
func (r *resolver) isNestedFs(f string) bool {
for ext := range r.factories {
if strings.HasSuffix(f, ext) {
return true
}
}
return true
}
// open requeue raw open, without resolver call
func (r *resolver) resolvePath(name string, rawOpen openFile) (fsPath string, nestedFs Filesystem, nestedFsPath string, err error) {
name = path.Clean(name)
name = strings.TrimPrefix(name, Separator)
parts := strings.Split(name, Separator)
@ -89,11 +124,12 @@ PARTS_LOOP:
}
if nestOn == -1 {
return clean(name), nil, "", nil
return AbsPath(name), nil, "", nil
}
fsPath = clean(strings.Join(parts[:nestOn], Separator))
nestedFsPath = clean(strings.Join(parts[nestOn:], Separator))
fsPath = AbsPath(path.Join(parts[:nestOn]...))
nestedFsPath = AbsPath(path.Join(parts[nestOn:]...))
// we dont need lock until now
// it must be before fsmap read to exclude race condition:
@ -123,9 +159,8 @@ PARTS_LOOP:
var ErrNotExist = fs.ErrNotExist
func getFile[F File](m map[string]F, name string) (File, error) {
name = clean(name)
if name == Separator {
return &Dir{}, nil
return &dir{}, nil
}
f, ok := m[name]
@ -135,27 +170,30 @@ func getFile[F File](m map[string]F, name string) (File, error) {
for p := range m {
if strings.HasPrefix(p, name) {
return &Dir{}, nil
return &dir{}, nil
}
}
return nil, ErrNotExist
}
func listFilesInDir[F File](m map[string]F, name string) (map[string]File, error) {
name = clean(name)
out := map[string]File{}
func listDirFromFiles[F File](m map[string]F, name string) ([]fs.DirEntry, error) {
out := make([]fs.DirEntry, 0, len(m))
name = AddTrailSlash(name)
for p, f := range m {
if strings.HasPrefix(p, name) {
parts := strings.Split(trimRelPath(p, name), Separator)
if len(parts) == 1 {
out[parts[0]] = f
out = append(out, newFileInfo(parts[0], f.Size()))
} else {
out[parts[0]] = &Dir{}
out = append(out, newDirInfo(parts[0]))
}
}
}
out = slices.CompactFunc(out, func(de1, de2 fs.DirEntry) bool {
return de1.Name() == de2.Name()
})
return out, nil
}