-
Notifications
You must be signed in to change notification settings - Fork 0
/
stdfs.go
136 lines (126 loc) · 3.52 KB
/
stdfs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package fs
import (
"errors"
"fmt"
iofs "io/fs"
"sort"
"strings"
)
var (
_ iofs.FS = StdFS{File("")}
_ iofs.SubFS = StdFS{File("")}
_ iofs.StatFS = StdFS{File("")}
// _ iofs.GlobFS = StdFS{File("")}
_ iofs.ReadDirFS = StdFS{File("")}
_ iofs.ReadFileFS = StdFS{File("")}
)
// StdFS implements the io/fs.FS interface
// of the standard library for a File.
//
// StdFS implements the following interfaces:
// - io/fs.FS
// - io/fs.SubFS
// - io/fs.StatFS
// - io/fs.GlobFS
// - io/fs.ReadDirFS
// - io/fs.ReadFileFS
type StdFS struct {
File File
}
// Stat returns a io/fs.FileInfo describing the file.
//
// This method implements the io/fs.StatFS interface.
func (f StdFS) Stat(name string) (iofs.FileInfo, error) {
return f.File.Join(name).Stat()
}
// Sub returns an io/fs.FS corresponding to the subtree rooted at dir.
//
// This method implements the io/fs.SubFS interface.
func (f StdFS) Sub(dir string) (iofs.FS, error) {
return f.File.Join(dir).StdFS(), nil
}
// Open opens the named file.
//
// This method implements the io/fs.FS interface.
func (f StdFS) Open(name string) (iofs.File, error) {
if err := checkStdFSName(name); err != nil {
return nil, err
}
return f.File.Join(name).OpenReader()
}
// ReadFile reads the named file and returns its contents.
//
// This method implements the io/fs.ReadFileFS interface.
func (f StdFS) ReadFile(name string) ([]byte, error) {
if err := checkStdFSName(name); err != nil {
return nil, err
}
return f.File.Join(name).ReadAll()
}
// ReadDir reads the named directory
// and returns a list of directory entries sorted by filename.
//
// This method implements the io/fs.ReadDirFS interface.
func (f StdFS) ReadDir(name string) ([]iofs.DirEntry, error) {
if err := checkStdFSName(name); err != nil {
return nil, err
}
var entries []iofs.DirEntry
err := f.File.Join(name).ListDir(func(file File) error {
entries = append(entries, file.StdDirEntry())
return nil
})
if err != nil {
return nil, err
}
sort.Slice(entries, func(i, j int) bool { return entries[i].Name() < entries[j].Name() })
return entries, nil
}
// Glob returns the names of all files matching pattern,
// providing an implementation of the top-level
// Glob function.
//
// This method implements the io/fs.GlobFS interface.
// func (f StdFS) Glob(pattern string) (names []string, err error) {
// // if pattern == `u[u][i-i][\d][\d-\d]i[r]/*e*` {
// // fmt.Println(pattern)
// // }
// if strings.Contains(pattern, "//") || strings.Contains(pattern, "[]") {
// return nil, fmt.Errorf("invalid glob pattern: %#v", pattern)
// }
// parentPattern, childPattern, cut := strings.Cut(pattern, "/")
// err = f.File.ListDir(
// func(file File) error {
// names = append(names, file.Name())
// return nil
// },
// parentPattern,
// )
// if err != nil {
// return nil, err
// }
// sort.Strings(names)
// if cut {
// parentNames := names
// names = nil // Don't include parents in final result
// for _, parent := range parentNames {
// children, err := f.File.Join(parent).StdFS().Glob(childPattern)
// if err != nil {
// return nil, err
// }
// for _, child := range children {
// names = append(names, path.Join(parent, child))
// }
// }
// }
// return names, nil
// }
func checkStdFSName(name string) error {
if name == "" {
return errors.New("empty filename")
}
if strings.HasPrefix(name, "/") || strings.HasSuffix(name, "/") || strings.Contains(name, "/.") || strings.Contains(name, "//") {
return fmt.Errorf("invalid filename: %s", name)
}
return nil
}