// 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 }