From 7c33c37e1017024b8c53a0ea4453ff48f81ced22 Mon Sep 17 00:00:00 2001 From: Nolan Woods Date: Sun, 16 Feb 2020 16:29:36 -0800 Subject: [PATCH] Change Dir to interface and add NewLazyDir() --- fs/dir.go | 87 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/fs/dir.go b/fs/dir.go index d876d89a61a0b..e63dc32ca2ae2 100644 --- a/fs/dir.go +++ b/fs/dir.go @@ -6,7 +6,16 @@ import ( ) // Dir describes an unspecialized directory for directory/container/bucket lists -type Dir struct { + +type Dir interface { + Directory + SetRemote(string) Dir + SetID(string) Dir + SetSize(int64) Dir + SetItems(int64) Dir +} + +type dir struct { remote string // name of the directory modTime time.Time // modification or creation time - IsZero for unknown size int64 // size of directory and contents or -1 if unknown @@ -14,9 +23,9 @@ type Dir struct { id string // optional ID } -// NewDir creates an unspecialized Directory object -func NewDir(remote string, modTime time.Time) *Dir { - return &Dir{ +// NewDir creates an unspecialized *dir object +func NewDir(remote string, modTime time.Time) Dir { + return &dir{ remote: remote, modTime: modTime, size: -1, @@ -24,47 +33,88 @@ func NewDir(remote string, modTime time.Time) *Dir { } } +type lazyDir struct { + dir + sizeGetter func() int64 + itemsGetter func() int64 +} + // NewDirCopy creates an unspecialized copy of the Directory object passed in -func NewDirCopy(ctx context.Context, d Directory) *Dir { - return &Dir{ +func NewDirCopy(ctx context.Context, d Directory) Dir { + dir := dir{ remote: d.Remote(), modTime: d.ModTime(ctx), size: d.Size(), items: d.Items(), id: d.ID(), } + if l, ok := d.(*lazyDir); ok { + return &lazyDir{ + dir: dir, + sizeGetter: l.sizeGetter, + itemsGetter: l.itemsGetter, + } + } + return &dir +} + +func (d *lazyDir) Size() int64 { + if d.dir.Size() == -1 { + d.SetSize(d.sizeGetter()) + } + return d.dir.Size() +} + +func (d *lazyDir) Items() int64 { + if d.dir.Items() == -1 { + d.SetItems(d.itemsGetter()) + } + return d.dir.Items() +} + +func NewLazyDir(remote string, modTime time.Time, sizeGetter func() int64, itemsGetter func() int64) Dir { + return &lazyDir{ + dir: dir{ + remote: remote, + modTime: modTime, + size: -1, + items: -1, + }, + sizeGetter: sizeGetter, + itemsGetter: itemsGetter, + } } // String returns the name -func (d *Dir) String() string { +func (d *dir) String() string { return d.remote } // Remote returns the remote path -func (d *Dir) Remote() string { +func (d *dir) Remote() string { return d.remote } // SetRemote sets the remote -func (d *Dir) SetRemote(remote string) *Dir { +func (d *dir) SetRemote(remote string) Dir { d.remote = remote return d } // ID gets the optional ID -func (d *Dir) ID() string { +func (d *dir) ID() string { return d.id } // SetID sets the optional ID -func (d *Dir) SetID(id string) *Dir { +func (d *dir) SetID(id string) Dir { d.id = id return d } // ModTime returns the modification date of the file // It should return a best guess if one isn't available -func (d *Dir) ModTime(ctx context.Context) time.Time { +func (d *dir) ModTime(ctx context.Context) time.Time { if !d.modTime.IsZero() { return d.modTime } @@ -72,30 +122,31 @@ func (d *Dir) ModTime(ctx context.Context) time.Time { } // Size returns the size of the file -func (d *Dir) Size() int64 { +func (d *dir) Size() int64 { return d.size } // SetSize sets the size of the directory -func (d *Dir) SetSize(size int64) *Dir { +func (d *dir) SetSize(size int64) Dir { d.size = size return d } // Items returns the count of items in this directory or this // directory and subdirectories if known, -1 for unknown -func (d *Dir) Items() int64 { +func (d *dir) Items() int64 { return d.items } // SetItems sets the number of items in the directory -func (d *Dir) SetItems(items int64) *Dir { +func (d *dir) SetItems(items int64) Dir { d.items = items return d } // Check interfaces var ( - _ DirEntry = (*Dir)(nil) - _ Directory = (*Dir)(nil) + _ Dir = (*dir)(nil) + _ DirEntry = (*dir)(nil) + _ Directory = (*dir)(nil) )