| // 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 ( | |
| "errors" | |
| "sort" | |
| ) | |
| // ReadDirFS is the interface implemented by a file system | |
| // that provides an optimized implementation of ReadDir. | |
| type ReadDirFS interface { | |
| FS | |
| // ReadDir reads the named directory | |
| // and returns a list of directory entries sorted by filename. | |
| ReadDir(name string) ([]DirEntry, error) | |
| } | |
| // ReadDir reads the named directory | |
| // and returns a list of directory entries sorted by filename. | |
| // | |
| // If fs implements ReadDirFS, ReadDir calls fs.ReadDir. | |
| // Otherwise ReadDir calls fs.Open and uses ReadDir and Close | |
| // on the returned file. | |
| func ReadDir(fsys FS, name string) ([]DirEntry, error) { | |
| if fsys, ok := fsys.(ReadDirFS); ok { | |
| return fsys.ReadDir(name) | |
| } | |
| file, err := fsys.Open(name) | |
| if err != nil { | |
| return nil, err | |
| } | |
| defer file.Close() | |
| dir, ok := file.(ReadDirFile) | |
| if !ok { | |
| return nil, &PathError{Op: "readdir", Path: name, Err: errors.New("not implemented")} | |
| } | |
| list, err := dir.ReadDir(-1) | |
| sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() }) | |
| return list, err | |
| } | |
| // dirInfo is a DirEntry based on a FileInfo. | |
| type dirInfo struct { | |
| fileInfo FileInfo | |
| } | |
| func (di dirInfo) IsDir() bool { | |
| return di.fileInfo.IsDir() | |
| } | |
| func (di dirInfo) Type() FileMode { | |
| return di.fileInfo.Mode().Type() | |
| } | |
| func (di dirInfo) Info() (FileInfo, error) { | |
| return di.fileInfo, nil | |
| } | |
| func (di dirInfo) Name() string { | |
| return di.fileInfo.Name() | |
| } | |
| // FileInfoToDirEntry returns a DirEntry that returns information from info. | |
| // If info is nil, FileInfoToDirEntry returns nil. | |
| func FileInfoToDirEntry(info FileInfo) DirEntry { | |
| if info == nil { | |
| return nil | |
| } | |
| return dirInfo{fileInfo: info} | |
| } |