Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update vfs to implement io/fs's fs.FS interface #163

Open
funkyshu opened this issue Feb 9, 2024 · 1 comment
Open

Update vfs to implement io/fs's fs.FS interface #163

funkyshu opened this issue Feb 9, 2024 · 1 comment

Comments

@funkyshu
Copy link
Member

funkyshu commented Feb 9, 2024

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
@funkyshu
Copy link
Member Author

funkyshu commented Feb 9, 2024

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'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant