github.com/haraldrudell/parl@v0.4.176/pfs/dir-entry-iterator.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package pfs 7 8 import ( 9 "io/fs" 10 "path/filepath" 11 "sync" 12 13 "github.com/haraldrudell/parl" 14 "github.com/haraldrudell/parl/iters" 15 ) 16 17 type DirEntry struct { 18 fs.DirEntry 19 ProvidedPath string 20 } 21 22 type DirEntryIterator struct { 23 path string 24 iters.BaseIterator[DirEntry] 25 sliceOnce sync.Once 26 err error 27 28 entriesLock sync.Mutex 29 entries []fs.DirEntry 30 } 31 32 func NewDirEntryIterator(path string) (iterator iters.Iterator[DirEntry]) { 33 i := DirEntryIterator{path: path} 34 i.BaseIterator = *iters.NewBaseIterator(i.iteratorAction) 35 return &i 36 } 37 38 // Init implements the right-hand side of a short variable declaration in 39 // the init statement of a Go “for” clause 40 // 41 // for i, iterator := iters.NewSlicePointerIterator(someSlice).Init(); iterator.Cond(&i); { 42 // // i is pointer to slice element 43 func (i *DirEntryIterator) Init() (result DirEntry, iterator iters.Iterator[DirEntry]) { 44 iterator = i 45 return 46 } 47 48 // iteratorAction provides items to the BaseIterator 49 func (t *DirEntryIterator) iteratorAction(isCancel bool) (result DirEntry, err error) { 50 if isCancel { 51 return 52 } 53 t.sliceOnce.Do(t.loadSlice) 54 if err = t.err; err != nil { 55 return 56 } 57 result.DirEntry = t.entry() 58 if result.DirEntry == nil { 59 err = parl.ErrEndCallbacks 60 return 61 } 62 result.ProvidedPath = filepath.Join(t.path, result.Name()) 63 return 64 } 65 66 func (t *DirEntryIterator) entry() (entry fs.DirEntry) { 67 t.entriesLock.Lock() 68 defer t.entriesLock.Unlock() 69 70 if len(t.entries) == 0 { 71 return 72 } 73 entry = t.entries[0] 74 t.entries[0] = nil 75 t.entries = t.entries[1:] 76 77 return 78 } 79 func (t *DirEntryIterator) loadSlice() { t.entries, t.err = ReadDir(t.path) }