diff --git a/groot/riofs/walk.go b/groot/riofs/walk.go index 3d152089e..dcfd41020 100644 --- a/groot/riofs/walk.go +++ b/groot/riofs/walk.go @@ -229,6 +229,22 @@ func fileOf(d Directory) *File { panic("impossible") } +// Get retrieves the named key from the provided directory. +func Get[T any](dir Directory, key string) (T, error) { + obj, err := Dir(dir).Get(key) + if err != nil { + var v T + return v, err + } + + v, ok := obj.(T) + if !ok { + return v, fmt.Errorf("riofs: could not convert %q (%T) to %T", key, obj, *new(T)) + } + + return v, nil +} + var ( _ Directory = (*recDir)(nil) ) diff --git a/groot/riofs/walk_example_test.go b/groot/riofs/walk_example_test.go index 1c1794a30..f0a60579d 100644 --- a/groot/riofs/walk_example_test.go +++ b/groot/riofs/walk_example_test.go @@ -10,6 +10,7 @@ import ( stdpath "path" "strings" + "go-hep.org/x/hep/groot/rhist" "go-hep.org/x/hep/groot/riofs" "go-hep.org/x/hep/groot/root" ) @@ -56,3 +57,20 @@ func ExampleWalk() { // dirs-6.14.00.root/dir1/dir11 (TDirectoryFile) // dirs-6.14.00.root/dir1/dir11/h1 (TH1F) } + +func ExampleGet() { + f, err := riofs.Open("../testdata/dirs-6.14.00.root") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + h1, err := riofs.Get[rhist.H1](f, "dir1/dir11/h1") + if err != nil { + log.Fatal(err) + } + fmt.Printf("histo: %s (%s)", h1.Name(), h1.Class()) + + // Output: + // histo: h1 (TH1F) +} diff --git a/groot/riofs/walk_test.go b/groot/riofs/walk_test.go index 4db181dcd..90bc9419b 100644 --- a/groot/riofs/walk_test.go +++ b/groot/riofs/walk_test.go @@ -13,9 +13,55 @@ import ( "testing" "go-hep.org/x/hep/groot/rbase" + "go-hep.org/x/hep/groot/rhist" "go-hep.org/x/hep/groot/root" ) +func TestGet(t *testing.T) { + f, err := Open("../testdata/dirs-6.14.00.root") + if err != nil { + t.Fatal(err) + } + defer f.Close() + + h1, err := Get[rhist.H1](f, "dir1/dir11/h1") + if err != nil { + t.Fatalf("could not get histo: %+v", err) + } + if h1 == nil { + t.Fatalf("invalid H1 value") + } + + h1f, err := Get[*rhist.H1F](f, "dir1/dir11/h1") + if err != nil { + t.Fatalf("could not get histo: %+v", err) + } + if h1f == nil { + t.Fatalf("invalid H1F value") + } + + _, err = Get[*rhist.H1D](f, "dir1/dir11/h1") + if err == nil { + t.Fatalf("expected an error") + } + if want := fmt.Errorf(`riofs: could not convert "dir1/dir11/h1" (*rhist.H1F) to *rhist.H1D`); err.Error() != want.Error() { + t.Fatalf("invalid error:\ngot= %+v\nwant=%+v", err, want) + } + + _, err = Get[any](f, "dir1/dir11/h1") + if err != nil { + t.Fatalf("could not get histo: %+v", err) + } + + _, err = Get[any](f, "dir1/dir11/h1_XXX") + if err == nil { + t.Fatalf("expected an error") + } + if want := fmt.Errorf(`riofs: dir11: could not find key "h1_XXX;9999"`); err.Error() != want.Error() { + t.Fatalf("invalid error:\ngot= %+v\nwant=%+v", err, want) + } + +} func TestDir(t *testing.T) { f, err := Open("../testdata/dirs-6.14.00.root") if err != nil {