readdir.mx raw
1 // Copyright 2020 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package fs
6
7 import (
8 "errors"
9 "internal/bytealg"
10 "slices"
11 )
12
13 // ReadDirFS is the interface implemented by a file system
14 // that provides an optimized implementation of [ReadDir].
15 type ReadDirFS interface {
16 FS
17
18 // ReadDir reads the named directory
19 // and returns a list of directory entries sorted by filename.
20 ReadDir(name string) ([]DirEntry, error)
21 }
22
23 // ReadDir reads the named directory
24 // and returns a list of directory entries sorted by filename.
25 //
26 // If fs implements [ReadDirFS], ReadDir calls fs.ReadDir.
27 // Otherwise ReadDir calls fs.Open and uses ReadDir and Close
28 // on the returned file.
29 func ReadDir(fsys FS, name []byte) ([]DirEntry, error) {
30 if fsys, ok := fsys.(ReadDirFS); ok {
31 return fsys.ReadDir(name)
32 }
33
34 file, err := fsys.Open(name)
35 if err != nil {
36 return nil, err
37 }
38 defer file.Close()
39
40 dir, ok := file.(ReadDirFile)
41 if !ok {
42 return nil, &PathError{Op: "readdir", Path: name, Err: errors.New("not implemented")}
43 }
44
45 list, err := dir.ReadDir(-1)
46 slices.SortFunc(list, func(a, b DirEntry) int {
47 return bytealg.CompareString(a.Name(), b.Name())
48 })
49 return list, err
50 }
51
52 // dirInfo is a DirEntry based on a FileInfo.
53 type dirInfo struct {
54 fileInfo FileInfo
55 }
56
57 func (di dirInfo) IsDir() bool {
58 return di.fileInfo.IsDir()
59 }
60
61 func (di dirInfo) Type() FileMode {
62 return di.fileInfo.Mode().Type()
63 }
64
65 func (di dirInfo) Info() (FileInfo, error) {
66 return di.fileInfo, nil
67 }
68
69 func (di dirInfo) Name() []byte {
70 return di.fileInfo.Name()
71 }
72
73 func (di dirInfo) String() string {
74 return FormatDirEntry(di)
75 }
76
77 // FileInfoToDirEntry returns a [DirEntry] that returns information from info.
78 // If info is nil, FileInfoToDirEntry returns nil.
79 func FileInfoToDirEntry(info FileInfo) DirEntry {
80 if info == nil {
81 return nil
82 }
83 return dirInfo{fileInfo: info}
84 }
85