171 lines
3.8 KiB
Go
171 lines
3.8 KiB
Go
// Package bindatafs provides wrapper vfs.FileSystem implementation to bridge
|
|
// go-bindata-generated assets to be served by http.FileServer.
|
|
package bindatafs
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path"
|
|
"syscall"
|
|
|
|
"golang.org/x/tools/godoc/vfs"
|
|
)
|
|
|
|
// FileSystem is a copy of vfs interface FileSystem
|
|
type FileSystem interface {
|
|
vfs.Opener
|
|
Lstat(path string) (os.FileInfo, error)
|
|
Stat(path string) (os.FileInfo, error)
|
|
ReadDir(path string) ([]os.FileInfo, error)
|
|
String() string
|
|
}
|
|
|
|
// New returns a FileSystem implementation of the given go-bindata generated assets
|
|
func New(name string, Asset AssetFunc, AssetDir AssetDirFunc, AssetInfo AssetInfoFunc) FileSystem {
|
|
return &binAssets{
|
|
name: name,
|
|
Asset: Asset,
|
|
AssetDir: AssetDir,
|
|
AssetInfo: AssetInfo,
|
|
}
|
|
}
|
|
|
|
// AssetFunc is the Assets() function generated by go-bindata
|
|
type AssetFunc func(name string) ([]byte, error)
|
|
|
|
// AssetDirFunc is the AssetDir() function generated by go-bindata
|
|
type AssetDirFunc func(name string) ([]string, error)
|
|
|
|
// AssetInfoFunc is the AssetInfo() function generated by go-bindata
|
|
type AssetInfoFunc func(name string) (os.FileInfo, error)
|
|
|
|
type binAssets struct {
|
|
name string
|
|
Asset AssetFunc
|
|
AssetDir AssetDirFunc
|
|
AssetInfo AssetInfoFunc
|
|
}
|
|
|
|
func (binAssets *binAssets) Open(pathname string) (file vfs.ReadSeekCloser, err error) {
|
|
|
|
pathname = binAssets.pathname(pathname)
|
|
|
|
// if is dir, return a dummy assetDir
|
|
if _, err = binAssets.AssetDir(pathname); err == nil {
|
|
err = &os.PathError{
|
|
Op: "Open",
|
|
Path: pathname,
|
|
Err: syscall.ENOENT,
|
|
}
|
|
return
|
|
}
|
|
|
|
// if is a file, return buffered data
|
|
var data []byte
|
|
if data, err = binAssets.Asset(pathname); err == nil {
|
|
file = &FileReader{Reader: bytes.NewReader(data)}
|
|
return
|
|
}
|
|
|
|
err = &os.PathError{
|
|
Op: "Open",
|
|
Path: pathname,
|
|
Err: syscall.ENOENT,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (binAssets *binAssets) Lstat(pathname string) (fi os.FileInfo, err error) {
|
|
return binAssets.Stat(pathname)
|
|
}
|
|
|
|
func (binAssets binAssets) pathname(pathname string) string {
|
|
if len(pathname) > 0 && pathname[0] == '/' {
|
|
return pathname[1:]
|
|
}
|
|
return pathname
|
|
}
|
|
|
|
func (binAssets *binAssets) Stat(pathname string) (fi os.FileInfo, err error) {
|
|
|
|
pathname = binAssets.pathname(pathname)
|
|
|
|
// if is dir, return a dummy assetDir
|
|
if _, err = binAssets.AssetDir(pathname); err == nil {
|
|
fi = &dirInfo{name: path.Base(pathname)}
|
|
return
|
|
}
|
|
|
|
// if is a file, return buffered data
|
|
if fi, err = binAssets.AssetInfo(pathname); err == nil {
|
|
fi = &fileInfo{name: path.Base(pathname), FileInfo: fi}
|
|
return
|
|
}
|
|
|
|
// return standard not found signal
|
|
err = &os.PathError{
|
|
Op: "Stat",
|
|
Path: pathname,
|
|
Err: syscall.ENOENT,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (binAssets *binAssets) ReadDir(pathname string) (fiList []os.FileInfo, err error) {
|
|
|
|
pathname = binAssets.pathname(pathname)
|
|
|
|
// if is a file, return error
|
|
if _, err = binAssets.AssetInfo(pathname); err == nil {
|
|
err = &os.PathError{
|
|
Op: "ReadDir",
|
|
Path: pathname,
|
|
Err: syscall.ENOENT,
|
|
}
|
|
return
|
|
}
|
|
|
|
// if is dir, return a dummy assetDir
|
|
var names []string
|
|
if names, err = binAssets.AssetDir(pathname); err != nil {
|
|
err = &os.PathError{
|
|
Op: "ReadDir",
|
|
Path: pathname,
|
|
Err: syscall.ENOENT,
|
|
}
|
|
return
|
|
}
|
|
|
|
// read all names entity to file info
|
|
fiList = make([]os.FileInfo, len(names))
|
|
for i, name := range names {
|
|
fiList[i], err = binAssets.Stat(path.Join(pathname, name))
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (binAssets *binAssets) String() string {
|
|
return binAssets.name
|
|
}
|
|
|
|
// FileReader implements vfs.ReadSeekCloser
|
|
type FileReader struct {
|
|
*bytes.Reader
|
|
}
|
|
|
|
// Read implements io.Reader
|
|
func (r *FileReader) Read(p []byte) (int, error) {
|
|
return r.Reader.Read(p)
|
|
}
|
|
|
|
// Seek implements io.Seeker
|
|
func (r *FileReader) Seek(offset int64, whence int) (int64, error) {
|
|
return r.Reader.Seek(offset, whence)
|
|
}
|
|
|
|
// Close implements io.Closer
|
|
func (r *FileReader) Close() error {
|
|
return nil
|
|
}
|