-
Notifications
You must be signed in to change notification settings - Fork 1
/
file.go
132 lines (116 loc) · 2.64 KB
/
file.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
package avfs
import (
"errors"
"io"
"io/fs"
"time"
)
// File is a virtual file.
// type File interface {
// Stat() (FileInfo, error)
// Read([]byte) (int, error)
// Close() error
// }
type File struct {
fi fs.FileInfo
offset int64 // current read offset
}
// NewFile returns a new file.
func NewFile(name string, contents []byte) *File {
return &File{
fi: &FileInfo{
name: name,
contents: contents,
isDir: false,
modTime: time.Now(),
fileMode: 0,
},
}
}
// Stat handler.
func (f *File) Stat() (fs.FileInfo, error) {
if f.fi == nil {
return nil, errors.New("invalid file")
}
return f.fi, nil
}
// Read handler.
func (f *File) Read(b []byte) (int, error) {
if f.offset >= int64(len(f.fi.Sys().([]byte))) {
return 0, io.EOF
}
if f.offset < 0 {
return 0, &fs.PathError{Op: "read", Path: f.fi.Name(), Err: fs.ErrInvalid}
}
n := copy(b, f.fi.Sys().([]byte)[f.offset:])
f.offset += int64(n)
return n, nil
}
// Seek handler.
func (f *File) Seek(offset int64, whence int) (int64, error) {
switch whence {
case 0:
// offset += 0
case 1:
offset += f.offset
case 2:
offset += int64(len(f.fi.Sys().([]byte)))
}
if offset < 0 || offset > int64(len(f.fi.Sys().([]byte))) {
return 0, &fs.PathError{Op: "seek", Path: f.fi.Name(), Err: fs.ErrInvalid}
}
f.offset = offset
return offset, nil
}
// Close handler.
func (f *File) Close() error {
f.offset = 0
return nil
}
// Info handler.
func (f *File) Info() (fs.FileInfo, error) {
return f.Stat()
}
// FileInfo is information on a file.
// type FileInfo interface {
// Name() string // base name of the file
// Size() int64 // length in bytes for regular files; system-dependent for others
// Mode() FileMode // file mode bits
// ModTime() time.Time // modification time
// IsDir() bool // abbreviation for Mode().IsDir()
// Sys() interface{} // underlying data source (can return nil)
// }
type FileInfo struct {
name string
contents []byte
isDir bool
modTime time.Time
fileMode fs.FileMode
}
// Name is the base name of the file.
func (f *FileInfo) Name() string {
return f.name
}
// Size is the length in bytes of the file.
func (f *FileInfo) Size() int64 {
return int64(len(f.contents))
}
// Mode is the file mode bits.
func (f *FileInfo) Mode() fs.FileMode {
if f.IsDir() {
return fs.ModeDir | 0555
}
return 0444
}
// ModTime is the modification time.
func (f *FileInfo) ModTime() time.Time {
return f.modTime
}
// IsDir returns true if a directory.
func (f *FileInfo) IsDir() bool {
return f.isDir
}
// Sys returns the file data.
func (f *FileInfo) Sys() interface{} {
return f.contents
}