| // Copyright 2020 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package fs | |
| import "io" | |
| // ReadFileFS is the interface implemented by a file system | |
| // that provides an optimized implementation of [ReadFile]. | |
| type ReadFileFS interface { | |
| FS | |
| // ReadFile reads the named file and returns its contents. | |
| // A successful call returns a nil error, not io.EOF. | |
| // (Because ReadFile reads the whole file, the expected EOF | |
| // from the final Read is not treated as an error to be reported.) | |
| // | |
| // The caller is permitted to modify the returned byte slice. | |
| // This method should return a copy of the underlying data. | |
| ReadFile(name string) ([]byte, error) | |
| } | |
| // ReadFile reads the named file from the file system fs and returns its contents. | |
| // A successful call returns a nil error, not [io.EOF]. | |
| // (Because ReadFile reads the whole file, the expected EOF | |
| // from the final Read is not treated as an error to be reported.) | |
| // | |
| // If fs implements [ReadFileFS], ReadFile calls fs.ReadFile. | |
| // Otherwise ReadFile calls fs.Open and uses Read and Close | |
| // on the returned [File]. | |
| func ReadFile(fsys FS, name string) ([]byte, error) { | |
| if fsys, ok := fsys.(ReadFileFS); ok { | |
| return fsys.ReadFile(name) | |
| } | |
| file, err := fsys.Open(name) | |
| if err != nil { | |
| return nil, err | |
| } | |
| defer file.Close() | |
| var size int | |
| if info, err := file.Stat(); err == nil { | |
| size64 := info.Size() | |
| if int64(int(size64)) == size64 { | |
| size = int(size64) | |
| } | |
| } | |
| data := make([]byte, 0, size+1) | |
| for { | |
| if len(data) >= cap(data) { | |
| d := append(data[:cap(data)], 0) | |
| data = d[:len(data)] | |
| } | |
| n, err := file.Read(data[len(data):cap(data)]) | |
| data = data[:len(data)+n] | |
| if err != nil { | |
| if err == io.EOF { | |
| err = nil | |
| } | |
| return data, err | |
| } | |
| } | |
| } | |