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 "golang.org/x/tools/godoc/vfs/httpfs" |
7 | |
8 | import ( |
9 | "fmt" |
10 | "io" |
11 | "net/http" |
12 | "os" |
13 | |
14 | "golang.org/x/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 | } |
95 |
Members