github.com/grailbio/base@v0.0.11/file/fsnode/parent.go (about) 1 package fsnode 2 3 import ( 4 "context" 5 "os" 6 7 "github.com/grailbio/base/log" 8 ) 9 10 // NewParent returns a Parent whose children are defined by gen. gen.GenerateChildren is called on 11 // every Parent query (including Child, which returns one result). Implementers should cache 12 // internally if necessary. 13 func NewParent(info FileInfo, gen ChildrenGenerator) Parent { 14 if !info.IsDir() { 15 log.Panicf("FileInfo has file mode, require directory: %#v", info) 16 } 17 return parentImpl{FileInfo: info, gen: gen} 18 } 19 20 type ( 21 // ChildrenGenerator generates child nodes. 22 ChildrenGenerator interface { 23 GenerateChildren(context.Context) ([]T, error) 24 } 25 childrenGenFunc func(context.Context) ([]T, error) 26 childrenGenConst []T 27 ) 28 29 // FuncChildren constructs a ChildrenGenerator that simply invokes fn, for convenience. 30 func FuncChildren(fn func(context.Context) ([]T, error)) ChildrenGenerator { 31 return childrenGenFunc(fn) 32 } 33 34 func (fn childrenGenFunc) GenerateChildren(ctx context.Context) ([]T, error) { return fn(ctx) } 35 36 // ConstChildren constructs a ChildrenGenerator that always returns the given children. 37 func ConstChildren(children ...T) ChildrenGenerator { 38 children = append([]T{}, children...) 39 return childrenGenConst(children) 40 } 41 42 func (c childrenGenConst) GenerateChildren(ctx context.Context) ([]T, error) { return c, nil } 43 44 type parentImpl struct { 45 ParentReadOnly 46 FileInfo 47 gen ChildrenGenerator 48 } 49 50 func (n parentImpl) Child(ctx context.Context, name string) (T, error) { 51 children, err := n.gen.GenerateChildren(ctx) 52 if err != nil { 53 return nil, err 54 } 55 for _, child := range children { 56 if child.Info().Name() == name { 57 return child, nil 58 } 59 } 60 return nil, os.ErrNotExist 61 } 62 63 func (n parentImpl) Children() Iterator { 64 return NewLazyIterator(n.gen.GenerateChildren) 65 } 66 67 func (n parentImpl) FSNodeT() {}