1 package httpdir 2 3 import ( 4 "bytes" 5 "io/fs" 6 "os" 7 "strings" 8 "time" 9 ) 10 11 type fileBytes struct { 12 data []byte 13 modTime time.Time 14 } 15 16 // FileBytes provides an implementation of Node that takes a byte slice as its 17 // data source 18 func FileBytes(data []byte, modTime time.Time) Node { 19 return fileBytes{ 20 data, 21 modTime, 22 } 23 } 24 25 func (f fileBytes) Size() int64 { 26 return int64(len(f.data)) 27 } 28 29 func (fileBytes) Mode() fs.FileMode { 30 return ModeFile 31 } 32 33 func (f fileBytes) ModTime() time.Time { 34 return f.modTime 35 } 36 37 func (f fileBytes) Open() (File, error) { 38 return fileBytesOpen{bytes.NewReader(f.data)}, nil 39 } 40 41 type fileBytesOpen struct { 42 *bytes.Reader 43 } 44 45 func (fileBytesOpen) Readdir(int) ([]fs.FileInfo, error) { 46 return nil, fs.ErrInvalid 47 } 48 49 func (fileBytesOpen) Close() error { 50 return nil 51 } 52 53 type fileString struct { 54 data string 55 modTime time.Time 56 } 57 58 // FileString provides an implementation of Node that takes a string as its 59 // data source 60 func FileString(data string, modTime time.Time) Node { 61 return fileString{ 62 data, 63 modTime, 64 } 65 } 66 67 func (f fileString) Size() int64 { 68 return int64(len(f.data)) 69 } 70 71 func (fileString) Mode() fs.FileMode { 72 return ModeFile 73 } 74 75 func (f fileString) ModTime() time.Time { 76 return f.modTime 77 } 78 79 func (f fileString) Open() (File, error) { 80 return fileStringOpen{strings.NewReader(f.data)}, nil 81 } 82 83 type fileStringOpen struct { 84 *strings.Reader 85 } 86 87 func (fileStringOpen) Readdir(int) ([]fs.FileInfo, error) { 88 return nil, fs.ErrInvalid 89 } 90 91 func (fileStringOpen) Close() error { 92 return nil 93 } 94 95 // OSFile is the path of a file in the real filesystem to be put into the 96 // im-memory filesystem 97 type OSFile string 98 99 // Size returns the size of the file 100 func (o OSFile) Size() int64 { 101 s, err := os.Stat(string(o)) 102 if err != nil { 103 return 0 104 } 105 return s.Size() 106 } 107 108 // Mode returns the Mode of the file 109 func (o OSFile) Mode() fs.FileMode { 110 s, err := os.Stat(string(o)) 111 if err != nil { 112 return 0 113 } 114 return s.Mode() 115 } 116 117 // ModTime returns the ModTime of the file 118 func (o OSFile) ModTime() time.Time { 119 s, err := os.Stat(string(o)) 120 if err != nil { 121 return time.Time{} 122 } 123 return s.ModTime() 124 } 125 126 // Open opens the file, returning it as a File 127 func (o OSFile) Open() (File, error) { 128 return os.Open(string(o)) 129 } 130 131 /* 132 // Compressed adds the given node to the Directory tree and gzip decompresses 133 // it into a FileBytes and also adds it to the tree. 134 // 135 // NB: The compressed version has .gz appended to its name 136 func Compressed(d Dir, name string, node Node, size int) error { 137 f, err := node.Open() 138 if err != nil { 139 return err 140 } 141 defer f.Close() 142 g, err := gzip.NewReader(f) 143 if err != nil { 144 return err 145 } 146 defer g.Close() 147 buf := make([]byte, size) 148 149 _, err = io.ReadFull(g, buf) 150 if err != nil { 151 return err 152 } 153 154 d.Create(name+".gz", node) 155 d.Create(name, FileBytes(buf, node.ModTime())) 156 return nil 157 } 158 */ 159