...
1 package storage
2
3 import (
4 "bytes"
5 "context"
6 "io"
7 "strings"
8 "sync"
9 "time"
10 )
11
12
13 func NewMemoryFS() FS {
14 return &memoryFS{
15 data: make(map[string]*memFile),
16 }
17 }
18
19 type memFile struct {
20 data []byte
21 attrs Attributes
22 }
23
24 func (f *memFile) readCloser() io.ReadCloser {
25 return io.NopCloser(bytes.NewReader(f.data))
26 }
27
28 type memoryFS struct {
29 sync.RWMutex
30
31 data map[string]*memFile
32 }
33
34
35 func (m *memoryFS) Open(_ context.Context, path string, _ *ReaderOptions) (*File, error) {
36 m.RLock()
37 f, ok := m.data[path]
38 m.RUnlock()
39
40 if ok {
41 return &File{
42 ReadCloser: f.readCloser(),
43 Attributes: f.attrs,
44 }, nil
45 }
46
47 return nil, ¬ExistError{
48 Path: path,
49 }
50 }
51
52
53 func (m *memoryFS) Attributes(_ context.Context, path string, _ *ReaderOptions) (*Attributes, error) {
54 m.RLock()
55 f, ok := m.data[path]
56 m.RUnlock()
57
58 if ok {
59 attrs := f.attrs
60
61 return &attrs, nil
62 }
63
64 return nil, ¬ExistError{
65 Path: path,
66 }
67 }
68
69 type writingFile struct {
70 *bytes.Buffer
71 path string
72
73 m *memoryFS
74 options *WriterOptions
75 }
76
77 func (wf *writingFile) Close() error {
78 if wf.options.Attributes.Size == 0 {
79 wf.options.Attributes.Size = int64(wf.Buffer.Len())
80 }
81
82 wf.m.Lock()
83
84 if wf.options.Attributes.ModTime.IsZero() {
85 wf.options.Attributes.ModTime = time.Now()
86 }
87 wf.m.data[wf.path] = &memFile{
88 data: wf.Buffer.Bytes(),
89 attrs: wf.options.Attributes,
90 }
91 wf.m.Unlock()
92
93 return nil
94 }
95
96
97 func (m *memoryFS) Create(_ context.Context, path string, options *WriterOptions) (io.WriteCloser, error) {
98 if options == nil {
99 options = &WriterOptions{}
100 }
101
102 return &writingFile{
103 Buffer: &bytes.Buffer{},
104 path: path,
105 m: m,
106 options: options,
107 }, nil
108 }
109
110
111 func (m *memoryFS) Delete(_ context.Context, path string) error {
112 m.Lock()
113 delete(m.data, path)
114 m.Unlock()
115
116 return nil
117 }
118
119
120 func (m *memoryFS) Walk(_ context.Context, path string, fn WalkFn) error {
121 var list []string
122 m.RLock()
123 for k := range m.data {
124 if strings.HasPrefix(k, path) {
125 list = append(list, k)
126 }
127 }
128 m.RUnlock()
129
130 for _, k := range list {
131 if err := fn(k); err != nil {
132 return err
133 }
134 }
135
136 return nil
137 }
138
139 func (m *memoryFS) URL(_ context.Context, _ string, _ *SignedURLOptions) (string, error) {
140 return "", ErrNotImplemented
141 }
142
View as plain text