-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
133 lines (120 loc) · 3.23 KB
/
utils.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
package fs
import (
"context"
"io"
"os"
"runtime"
)
// FileURLs returns the URLs of the passed files
func FileURLs(files []File) []string {
fileURLs := make([]string, len(files))
for i, file := range files {
fileURLs[i] = file.URL()
}
return fileURLs
}
// FilePaths returns the FileSystem specific paths the passed files
func FilePaths(files []File) []string {
paths := make([]string, len(files))
for i, file := range files {
paths[i] = file.Path()
}
return paths
}
// FileNames returns the names of the passed files
func FileNames[T FileReader](files []T) []string {
names := make([]string, len(files))
for i, file := range files {
names[i] = file.Name()
}
return names
}
// FilesAsFileReaders converts a slice of File to a slice of FileReader
func FilesAsFileReaders(files []File) []FileReader {
fileReaders := make([]FileReader, len(files))
for i, file := range files {
fileReaders[i] = file
}
return fileReaders
}
// FilesFromStrings returns Files for the given fileURIs.
func FilesFromStrings(fileURIs []string) []File {
files := make([]File, len(fileURIs))
for i := range fileURIs {
files[i] = File(fileURIs[i])
}
return files
}
// FileReadersFromStrings returns FileReaders for the given fileURIs.
func FileReadersFromStrings(fileURIs []string) []FileReader {
fileReaders := make([]FileReader, len(fileURIs))
for i := range fileURIs {
fileReaders[i] = File(fileURIs[i])
}
return fileReaders
}
// FileInfoToFileCallback converts a File callback function
// into a FileInfo callback function that is calling
// the passed fileCallback with the FileInfo.File.
func FileInfoToFileCallback(fileCallback func(File) error) func(*FileInfo) error {
return func(info *FileInfo) error {
return fileCallback(info.File)
}
}
// ReadAllContext reads all data from r until EOF is reached,
// another error is returned, or the context got canceled.
// It is identical to io.ReadAll except that
// it can be canceled via a context.
func ReadAllContext(ctx context.Context, r io.Reader) ([]byte, error) {
b := make([]byte, 0, 512)
for ctx.Err() == nil {
if len(b) == cap(b) {
// Add more capacity (let append pick how much).
b = append(b, 0)[:len(b)]
}
n, err := r.Read(b[len(b):cap(b)])
b = b[:len(b)+n]
if err != nil {
if err == io.EOF {
return b, nil
}
return b, err
}
}
return b, ctx.Err()
}
// WriteAllContext writes all data wo the to w
// with a cancelable context.
func WriteAllContext(ctx context.Context, w io.Writer, data []byte) error {
const chunkSize = 4 * 1024 * 1024 // 4MB
return writeAllContext(ctx, w, data, chunkSize)
}
func writeAllContext(ctx context.Context, w io.Writer, data []byte, chunkSize int) error {
for len(data) > 0 {
if err := ctx.Err(); err != nil {
return err
}
n, err := w.Write(data[:min(chunkSize, len(data))])
if err != nil {
return err
}
data = data[n:]
}
return nil
}
// ExecutableFile returns a File for the executable that started the current process.
// It wraps os.ExecutableFile, see https://golang.org/pkg/os/#ExecutableFile
func ExecutableFile() File {
exe, err := os.Executable()
if err != nil {
return InvalidFile
}
return File(exe)
}
func SourceFile() File {
_, file, _, ok := runtime.Caller(1)
if !ok {
return InvalidFile
}
return File(file)
}