github.com/v2fly/tools@v0.100.0/godoc/vfs/httpfs/httpfs.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package httpfs implements http.FileSystem using a godoc vfs.FileSystem. 6 package httpfs // import "github.com/v2fly/tools/godoc/vfs/httpfs" 7 8 import ( 9 "fmt" 10 "io" 11 "net/http" 12 "os" 13 14 "github.com/v2fly/tools/godoc/vfs" 15 ) 16 17 func New(fs vfs.FileSystem) http.FileSystem { 18 return &httpFS{fs} 19 } 20 21 type httpFS struct { 22 fs vfs.FileSystem 23 } 24 25 func (h *httpFS) Open(name string) (http.File, error) { 26 fi, err := h.fs.Stat(name) 27 if err != nil { 28 return nil, err 29 } 30 if fi.IsDir() { 31 return &httpDir{h.fs, name, nil}, nil 32 } 33 f, err := h.fs.Open(name) 34 if err != nil { 35 return nil, err 36 } 37 return &httpFile{h.fs, f, name}, nil 38 } 39 40 // httpDir implements http.File for a directory in a FileSystem. 41 type httpDir struct { 42 fs vfs.FileSystem 43 name string 44 pending []os.FileInfo 45 } 46 47 func (h *httpDir) Close() error { return nil } 48 func (h *httpDir) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) } 49 func (h *httpDir) Read([]byte) (int, error) { 50 return 0, fmt.Errorf("cannot Read from directory %s", h.name) 51 } 52 53 func (h *httpDir) Seek(offset int64, whence int) (int64, error) { 54 if offset == 0 && whence == 0 { 55 h.pending = nil 56 return 0, nil 57 } 58 return 0, fmt.Errorf("unsupported Seek in directory %s", h.name) 59 } 60 61 func (h *httpDir) Readdir(count int) ([]os.FileInfo, error) { 62 if h.pending == nil { 63 d, err := h.fs.ReadDir(h.name) 64 if err != nil { 65 return nil, err 66 } 67 if d == nil { 68 d = []os.FileInfo{} // not nil 69 } 70 h.pending = d 71 } 72 73 if len(h.pending) == 0 && count > 0 { 74 return nil, io.EOF 75 } 76 if count <= 0 || count > len(h.pending) { 77 count = len(h.pending) 78 } 79 d := h.pending[:count] 80 h.pending = h.pending[count:] 81 return d, nil 82 } 83 84 // httpFile implements http.File for a file (not directory) in a FileSystem. 85 type httpFile struct { 86 fs vfs.FileSystem 87 vfs.ReadSeekCloser 88 name string 89 } 90 91 func (h *httpFile) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) } 92 func (h *httpFile) Readdir(int) ([]os.FileInfo, error) { 93 return nil, fmt.Errorf("cannot Readdir from file %s", h.name) 94 }