Update vfs to implement io/fs's fs.FS interface
funkyshu opened this issue · comments
Is your feature request related to a problem? Please describe.
Implement https://pkg.go.dev/io/fs#FS should consist of adding the following func
Open(name string) (File, error)
which returns a File:
type File interface {
Stat() (FileInfo, error)
Read([]byte) (int, error)
Close() error
}
where Stat() can return a FileInfo:
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() any // underlying data source (can return nil)
}
Describe the solution you'd like
I think it makes the most sense to:
- add
Stat() (FileInfo, error)
to the vfs.File interface - add
Open(name string) (File, error)
to the Location interface.
The implementation of Open could simply be:
func (loc *Location) Open(name string) (fs.File, error){
return loc.NewFile(name)
}
The the overall usage would be like:
osfs := os.NewFilesystem()
// setup location
loc, _ := osfs.NewLocation("c:", "/some/path/")
// use fs.FS func
file, _ := Open("somefile.txt")
// use fs.File func
fileinfo, _ := file.Stat()
fmt.Printf("name: '%s' size: %d", fileinfo.Name(), fileinfo.Size()) // name: 'somefile.txt' size: 123
fmt.Printf("name: '%s' size: %d", file.(*os.File).Name(), file.(*os.File).Size()) // name: 'somefile.txt' size: 123
or for S3:
s3fs := s3.NewFilesystem()
s3fs= s3fs.(*s3.Filesystem).WithOptions(
s3.Options{
AccessKeyID: "AKIAIOSFODNN7EXAMPLE",
SecretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
Region: "us-west-2",
ACL: "bucket-owner-full-control",
},
)
// setup location
loc, _ := s3fs.NewLocation("myBucket", "/some/path/")
// use fs.FS func
file, _ := Open("somefile.txt")
// use fs.File func
fileinfo, _ := file.Stat()
fmt.Printf("name: '%s' size: %d", fileinfo.Name(), fileinfo.Size()) // name: 'somefile.txt' size: 123
fmt.Printf("name: '%s' size: %d", file.(*s3.File).Name(), file.(*s3.File).Size()) // name: 'somefile.txt' size: 123
Alternatively:
We could make vfs.Filesystem
implement fs.FS
so that you specify a the schema-less portion of the uri (authority + path) with Open()
. Then both vfs.Location
and vfs.File
would implement fs.File
.
osfs := os.NewFileSystem()
// open a dir
loc, _ := osfs.Open("c:/some/path/)
fileinfo,_ := loc.Stat()
fmt.Printf("name: '%s'", fileinfo.Name()) // name: 'path'
fmt.Printf("name: '%s'", loc.(*os.Location).Name()) // name: 'path'
// open a file
file, _ := osfs.Open("c:/some/path/to/file.txt")
fileinfo,_ := file.Stat()
fmt.Printf("name: '%s'", fileinfo.Name()) // name: 'file.txt'
fmt.Printf("name: '%s'", file.(*os.File).Name()) // name: 'file.txt'
or for s3:
s3fs := s3.NewFileSystem()
s3fs = s3fs.(*s3.Filiesystem).WithOptions(
s3.Options{
AccessKeyID: "AKIAIOSFODNN7EXAMPLE",
SecretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
Region: "us-west-2",
ACL: "bucket-owner-full-control",
},
)
// open a dir
loc, _ := s3fs.Open("myBucket/some/path/)
fileinfo,_ := loc.Stat()
fmt.Printf("name: '%s'", loc.Name()) // name: 'path'
fmt.Printf("name: '%s'", loc.(*s3.Location).Name()) // name: 'path'
// open a file
file, _ := s3fs.Open("myBucket/some/path/to/file.txt")
fileinfo,_ := file.Stat()
fmt.Printf("name: '%s'", fileinfo.Name()) // name: 'file.txt'
fmt.Printf("name: '%s'", file.(*s3.File).Name()) // name: 'file.txt'