| // Copyright 2013 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package httpfs implements http.FileSystem using a godoc vfs.FileSystem. |
| package httpfs // import "golang.org/x/tools/godoc/vfs/httpfs" |
| |
| import ( |
| "fmt" |
| "io" |
| "net/http" |
| "os" |
| |
| "golang.org/x/tools/godoc/vfs" |
| ) |
| |
| func New(fs vfs.FileSystem) http.FileSystem { |
| return &httpFS{fs} |
| } |
| |
| type httpFS struct { |
| fs vfs.FileSystem |
| } |
| |
| func (h *httpFS) Open(name string) (http.File, error) { |
| fi, err := h.fs.Stat(name) |
| if err != nil { |
| return nil, err |
| } |
| if fi.IsDir() { |
| return &httpDir{h.fs, name, nil}, nil |
| } |
| f, err := h.fs.Open(name) |
| if err != nil { |
| return nil, err |
| } |
| return &httpFile{h.fs, f, name}, nil |
| } |
| |
| // httpDir implements http.File for a directory in a FileSystem. |
| type httpDir struct { |
| fs vfs.FileSystem |
| name string |
| pending []os.FileInfo |
| } |
| |
| func (h *httpDir) Close() error { return nil } |
| func (h *httpDir) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) } |
| func (h *httpDir) Read([]byte) (int, error) { |
| return 0, fmt.Errorf("cannot Read from directory %s", h.name) |
| } |
| |
| func (h *httpDir) Seek(offset int64, whence int) (int64, error) { |
| if offset == 0 && whence == 0 { |
| h.pending = nil |
| return 0, nil |
| } |
| return 0, fmt.Errorf("unsupported Seek in directory %s", h.name) |
| } |
| |
| func (h *httpDir) Readdir(count int) ([]os.FileInfo, error) { |
| if h.pending == nil { |
| d, err := h.fs.ReadDir(h.name) |
| if err != nil { |
| return nil, err |
| } |
| if d == nil { |
| d = []os.FileInfo{} // not nil |
| } |
| h.pending = d |
| } |
| |
| if len(h.pending) == 0 && count > 0 { |
| return nil, io.EOF |
| } |
| if count <= 0 || count > len(h.pending) { |
| count = len(h.pending) |
| } |
| d := h.pending[:count] |
| h.pending = h.pending[count:] |
| return d, nil |
| } |
| |
| // httpFile implements http.File for a file (not directory) in a FileSystem. |
| type httpFile struct { |
| fs vfs.FileSystem |
| vfs.ReadSeekCloser |
| name string |
| } |
| |
| func (h *httpFile) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) } |
| func (h *httpFile) Readdir(int) ([]os.FileInfo, error) { |
| return nil, fmt.Errorf("cannot Readdir from file %s", h.name) |
| } |