@@ -11,6 +11,8 @@ import (
1111)
1212
1313var _ fs.FS = FS (nil )
14+ var _ fs.StatFS = FS (nil )
15+ var _ fs.ReadDirFS = FS (nil )
1416
1517type FS map [string ]Entry
1618
@@ -21,11 +23,7 @@ func (f FS) Open(name string) (fs.File, error) {
2123 }
2224
2325 // Normalize the path
24- trimmed := path .Clean (name )
25- trimmed = strings .Trim (trimmed , "/" )
26- if trimmed == "." {
27- trimmed = ""
28- }
26+ trimmed := normalizePath (name )
2927
3028 // Find the entry with the pathname
3129 entry , ok := f [trimmed ]
@@ -40,26 +38,46 @@ func (f FS) Open(name string) (fs.File, error) {
4038 }
4139
4240 // Wrap the file in a struct that implements the fs.File interface
43- basename := path .Base (trimmed )
41+ basename := path .Base (name )
4442 return & inMemFile {
4543 reader : io .NopCloser (bytes .NewReader (fileEntry )),
4644 entry : fileEntry .ToEntry (basename ),
4745 }, nil
4846}
4947
50- func (f FS ) ReadDir (name string ) ([] fs.DirEntry , error ) {
48+ func (f FS ) Stat (name string ) (fs.FileInfo , error ) {
5149 // If the map is nil, return an error
5250 if f == nil {
5351 return nil , fs .ErrNotExist
5452 }
5553
5654 // Normalize the path
57- trimmed := path .Clean (name )
58- trimmed = strings .Trim (trimmed , "/" )
59- if trimmed == "." {
60- trimmed = ""
55+ trimmed := normalizePath (name )
56+ basename := path .Base (trimmed )
57+
58+ // Find the entry with the pathname
59+ entry , ok := f [trimmed ]
60+ if ok {
61+ return entry .ToEntry (basename ).Info ()
62+ }
63+
64+ // Check if there are any child entries
65+ entries := f .getEntriesInDir (trimmed )
66+ if len (entries ) > 0 {
67+ return Dir {}.ToEntry (basename ).Info ()
68+ }
69+ return nil , fs .ErrNotExist
70+ }
71+
72+ func (f FS ) ReadDir (name string ) ([]fs.DirEntry , error ) {
73+ // If the map is nil, return an error
74+ if f == nil {
75+ return nil , fs .ErrNotExist
6176 }
6277
78+ // Normalize the path
79+ trimmed := normalizePath (name )
80+
6381 // Check if there is an empty directory entry at the path
6482 entryAtPath , hasEntry := f [trimmed ]
6583 if hasEntry {
@@ -69,6 +87,23 @@ func (f FS) ReadDir(name string) ([]fs.DirEntry, error) {
6987 }
7088 }
7189
90+ // Get all the child entries of this path
91+ entries := f .getEntriesInDir (trimmed )
92+
93+ // If there are no entries, and also no empty dir nodes, return an error
94+ if len (entries ) == 0 && ! hasEntry && trimmed != "" {
95+ return nil , fs .ErrNotExist
96+ }
97+
98+ // Sort the entries by name
99+ slices .SortFunc (entries , func (a , b fs.DirEntry ) int {
100+ return strings .Compare (a .Name (), b .Name ())
101+ })
102+
103+ return entries , nil
104+ }
105+
106+ func (f FS ) getEntriesInDir (trimmed string ) []fs.DirEntry {
72107 // Look for all the entries that are children of the dir path
73108 var entries []fs.DirEntry
74109 intermediateDirs := make (map [string ]struct {})
@@ -93,16 +128,14 @@ func (f FS) ReadDir(name string) ([]fs.DirEntry, error) {
93128 // Add the entry to the list of entries
94129 entries = append (entries , entry .ToEntry (suffix ))
95130 }
131+ return entries
132+ }
96133
97- // If there are no entries, and also no empty dir nodes, return an error
98- if len (entries ) == 0 && ! hasEntry && trimmed != "" {
99- return nil , fs .ErrNotExist
134+ func normalizePath (name string ) string {
135+ trimmed := path .Clean (name )
136+ trimmed = strings .Trim (trimmed , "/" )
137+ if trimmed == "." {
138+ trimmed = ""
100139 }
101-
102- // Sort the entries by name
103- slices .SortFunc (entries , func (a , b fs.DirEntry ) int {
104- return strings .Compare (a .Name (), b .Name ())
105- })
106-
107- return entries , nil
140+ return trimmed
108141}
0 commit comments