Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / godoc / vfs / mapfs / mapfs.go
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 mapfs file provides an implementation of the FileSystem
6 // interface based on the contents of a map[string]string.
7 package mapfs // import "golang.org/x/tools/godoc/vfs/mapfs"
8
9 import (
10         "fmt"
11         "io"
12         "os"
13         pathpkg "path"
14         "sort"
15         "strings"
16         "time"
17
18         "golang.org/x/tools/godoc/vfs"
19 )
20
21 // New returns a new FileSystem from the provided map.
22 // Map keys must be forward slash-separated paths with
23 // no leading slash, such as "file1.txt" or "dir/file2.txt".
24 // New panics if any of the paths contain a leading slash.
25 func New(m map[string]string) vfs.FileSystem {
26         // Verify all provided paths are relative before proceeding.
27         var pathsWithLeadingSlash []string
28         for p := range m {
29                 if strings.HasPrefix(p, "/") {
30                         pathsWithLeadingSlash = append(pathsWithLeadingSlash, p)
31                 }
32         }
33         if len(pathsWithLeadingSlash) > 0 {
34                 panic(fmt.Errorf("mapfs.New: invalid paths with a leading slash: %q", pathsWithLeadingSlash))
35         }
36
37         return mapFS(m)
38 }
39
40 // mapFS is the map based implementation of FileSystem
41 type mapFS map[string]string
42
43 func (fs mapFS) String() string { return "mapfs" }
44
45 func (fs mapFS) RootType(p string) vfs.RootType {
46         return ""
47 }
48
49 func (fs mapFS) Close() error { return nil }
50
51 func filename(p string) string {
52         return strings.TrimPrefix(p, "/")
53 }
54
55 func (fs mapFS) Open(p string) (vfs.ReadSeekCloser, error) {
56         b, ok := fs[filename(p)]
57         if !ok {
58                 return nil, os.ErrNotExist
59         }
60         return nopCloser{strings.NewReader(b)}, nil
61 }
62
63 func fileInfo(name, contents string) os.FileInfo {
64         return mapFI{name: pathpkg.Base(name), size: len(contents)}
65 }
66
67 func dirInfo(name string) os.FileInfo {
68         return mapFI{name: pathpkg.Base(name), dir: true}
69 }
70
71 func (fs mapFS) Lstat(p string) (os.FileInfo, error) {
72         b, ok := fs[filename(p)]
73         if ok {
74                 return fileInfo(p, b), nil
75         }
76         ents, _ := fs.ReadDir(p)
77         if len(ents) > 0 {
78                 return dirInfo(p), nil
79         }
80         return nil, os.ErrNotExist
81 }
82
83 func (fs mapFS) Stat(p string) (os.FileInfo, error) {
84         return fs.Lstat(p)
85 }
86
87 // slashdir returns path.Dir(p), but special-cases paths not beginning
88 // with a slash to be in the root.
89 func slashdir(p string) string {
90         d := pathpkg.Dir(p)
91         if d == "." {
92                 return "/"
93         }
94         if strings.HasPrefix(p, "/") {
95                 return d
96         }
97         return "/" + d
98 }
99
100 func (fs mapFS) ReadDir(p string) ([]os.FileInfo, error) {
101         p = pathpkg.Clean(p)
102         var ents []string
103         fim := make(map[string]os.FileInfo) // base -> fi
104         for fn, b := range fs {
105                 dir := slashdir(fn)
106                 isFile := true
107                 var lastBase string
108                 for {
109                         if dir == p {
110                                 base := lastBase
111                                 if isFile {
112                                         base = pathpkg.Base(fn)
113                                 }
114                                 if fim[base] == nil {
115                                         var fi os.FileInfo
116                                         if isFile {
117                                                 fi = fileInfo(fn, b)
118                                         } else {
119                                                 fi = dirInfo(base)
120                                         }
121                                         ents = append(ents, base)
122                                         fim[base] = fi
123                                 }
124                         }
125                         if dir == "/" {
126                                 break
127                         } else {
128                                 isFile = false
129                                 lastBase = pathpkg.Base(dir)
130                                 dir = pathpkg.Dir(dir)
131                         }
132                 }
133         }
134         if len(ents) == 0 {
135                 return nil, os.ErrNotExist
136         }
137
138         sort.Strings(ents)
139         var list []os.FileInfo
140         for _, dir := range ents {
141                 list = append(list, fim[dir])
142         }
143         return list, nil
144 }
145
146 // mapFI is the map-based implementation of FileInfo.
147 type mapFI struct {
148         name string
149         size int
150         dir  bool
151 }
152
153 func (fi mapFI) IsDir() bool        { return fi.dir }
154 func (fi mapFI) ModTime() time.Time { return time.Time{} }
155 func (fi mapFI) Mode() os.FileMode {
156         if fi.IsDir() {
157                 return 0755 | os.ModeDir
158         }
159         return 0444
160 }
161 func (fi mapFI) Name() string     { return pathpkg.Base(fi.name) }
162 func (fi mapFI) Size() int64      { return int64(fi.size) }
163 func (fi mapFI) Sys() interface{} { return nil }
164
165 type nopCloser struct {
166         io.ReadSeeker
167 }
168
169 func (nc nopCloser) Close() error { return nil }