// 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" "internal/bytealg" "slices" ) // 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) slices.SortFunc(list, func(a, b DirEntry) int { return bytealg.CompareString(a.Name(), b.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() } func (di dirInfo) String() string { return FormatDirEntry(di) } // 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} }