2019-07-01 15:11:23 +01:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package asset
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var _ http.FileSystem = (*InmemoryFileSystem)(nil)
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// InmemoryFileSystem defines an inmemory http.FileSystem.
|
2019-07-01 15:11:23 +01:00
|
|
|
type InmemoryFileSystem struct {
|
|
|
|
Root *Asset
|
|
|
|
Index map[string]*Asset
|
|
|
|
}
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// Inmemory creates an InmemoryFileSystem from.
|
2019-07-01 15:11:23 +01:00
|
|
|
func Inmemory(root *Asset) *InmemoryFileSystem {
|
|
|
|
fs := &InmemoryFileSystem{}
|
|
|
|
fs.Root = root
|
|
|
|
fs.Index = map[string]*Asset{}
|
|
|
|
fs.reindex("/", "", root)
|
|
|
|
return fs
|
|
|
|
}
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// reindex inserts a node to the index.
|
2019-07-01 15:11:23 +01:00
|
|
|
func (fs *InmemoryFileSystem) reindex(prefix, name string, file *Asset) {
|
|
|
|
fs.Index[path.Join(prefix, name)] = file
|
|
|
|
for _, child := range file.Children {
|
|
|
|
fs.reindex(path.Join(prefix, name), child.Name, child)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open opens the file at the specified path.
|
|
|
|
func (fs *InmemoryFileSystem) Open(path string) (http.File, error) {
|
|
|
|
asset, ok := fs.Index[path]
|
|
|
|
if !ok {
|
|
|
|
return nil, os.ErrNotExist
|
|
|
|
}
|
|
|
|
return asset.File(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// File opens the particular asset as a file.
|
|
|
|
func (asset *Asset) File() *File {
|
|
|
|
return &File{*bytes.NewReader(asset.Data), asset}
|
|
|
|
}
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// File defines a readable file.
|
2019-07-01 15:11:23 +01:00
|
|
|
type File struct {
|
|
|
|
bytes.Reader
|
|
|
|
*Asset
|
|
|
|
}
|
|
|
|
|
|
|
|
// Readdir reads all file infos from the directory.
|
|
|
|
func (file *File) Readdir(count int) ([]os.FileInfo, error) {
|
|
|
|
if !file.Mode.IsDir() {
|
|
|
|
return nil, errors.New("not a directory")
|
|
|
|
}
|
|
|
|
|
|
|
|
if count > len(file.Children) {
|
|
|
|
count = len(file.Children)
|
|
|
|
}
|
|
|
|
|
|
|
|
infos := make([]os.FileInfo, 0, count)
|
|
|
|
for _, child := range file.Children {
|
|
|
|
infos = append(infos, child.stat())
|
|
|
|
}
|
|
|
|
|
|
|
|
return infos, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (asset *Asset) stat() FileInfo {
|
|
|
|
return FileInfo{
|
|
|
|
name: asset.Name,
|
|
|
|
size: int64(len(asset.Data)),
|
|
|
|
mode: asset.Mode,
|
|
|
|
modTime: asset.ModTime,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stat returns stats about the file.
|
|
|
|
func (file *File) Stat() (os.FileInfo, error) { return file.stat(), nil }
|
|
|
|
|
|
|
|
// Close closes the file.
|
|
|
|
func (file *File) Close() error { return nil }
|
|
|
|
|
|
|
|
// FileInfo implements file info.
|
|
|
|
type FileInfo struct {
|
|
|
|
name string
|
|
|
|
size int64
|
|
|
|
mode os.FileMode
|
|
|
|
modTime time.Time
|
|
|
|
}
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// Name implements os.FileInfo.
|
2019-07-01 15:11:23 +01:00
|
|
|
func (info FileInfo) Name() string { return info.name }
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// Size implements os.FileInfo.
|
2019-07-01 15:11:23 +01:00
|
|
|
func (info FileInfo) Size() int64 { return info.size }
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// Mode implements os.FileInfo.
|
2019-07-01 15:11:23 +01:00
|
|
|
func (info FileInfo) Mode() os.FileMode { return info.mode }
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// ModTime implements os.FileInfo.
|
2019-07-01 15:11:23 +01:00
|
|
|
func (info FileInfo) ModTime() time.Time { return info.modTime }
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// IsDir implements os.FileInfo.
|
2019-07-01 15:11:23 +01:00
|
|
|
func (info FileInfo) IsDir() bool { return info.mode.IsDir() }
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// Sys implements os.FileInfo.
|
2019-07-01 15:11:23 +01:00
|
|
|
func (info FileInfo) Sys() interface{} { return nil }
|