go-hep.org/x/hep@v0.38.1/groot/rtree/rleaf.go (about)

     1  // Copyright ©2020 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package rtree
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"unsafe"
    11  
    12  	"go-hep.org/x/hep/groot/rbytes"
    13  	"go-hep.org/x/hep/groot/rdict"
    14  )
    15  
    16  // rleafCtx is the interface that wraps the rcount method.
    17  type rleafCtx interface {
    18  	// rcountFunc returns the function that gives the leaf-count
    19  	// of the provided leaf.
    20  	rcountFunc(leaf string) func() int
    21  	rcountLeaf(leaf string) leafCount
    22  }
    23  
    24  // rleaf is the leaf reading interface.
    25  type rleaf interface {
    26  	Leaf() Leaf
    27  	Offset() int64
    28  	readFromBuffer(*rbytes.RBuffer) error
    29  }
    30  
    31  // rleafDefaultSliceCap is the default capacity for all
    32  // rleaves that hold slices of data.
    33  const rleafDefaultSliceCap = 8
    34  
    35  func rleafFrom(leaf Leaf, rvar ReadVar, rctx rleafCtx) rleaf {
    36  	switch leaf := leaf.(type) {
    37  	case *LeafO:
    38  		return newRLeafBool(leaf, rvar, rctx)
    39  	case *LeafB:
    40  		switch rv := reflect.ValueOf(rvar.Value); rv.Interface().(type) {
    41  		case *int8, *[]int8:
    42  			return newRLeafI8(leaf, rvar, rctx)
    43  		case *uint8, *[]uint8:
    44  			return newRLeafU8(leaf, rvar, rctx)
    45  		default:
    46  			rv := rv.Elem()
    47  			switch rv.Kind() {
    48  			case reflect.Array:
    49  				rt, _ := flattenArrayType(rv.Type())
    50  				switch rt.Kind() {
    51  				case reflect.Int8:
    52  					return newRLeafI8(leaf, rvar, rctx)
    53  				case reflect.Uint8:
    54  					return newRLeafU8(leaf, rvar, rctx)
    55  				}
    56  			case reflect.Slice:
    57  				rt, _ := flattenArrayType(rv.Type().Elem())
    58  				switch rt.Kind() {
    59  				case reflect.Int8:
    60  					return newRLeafI8(leaf, rvar, rctx)
    61  				case reflect.Uint8:
    62  					return newRLeafU8(leaf, rvar, rctx)
    63  				}
    64  			}
    65  		}
    66  		panic(fmt.Errorf("rvar mismatch for %T", leaf))
    67  	case *LeafS:
    68  		switch rv := reflect.ValueOf(rvar.Value); rv.Interface().(type) {
    69  		case *int16, *[]int16:
    70  			return newRLeafI16(leaf, rvar, rctx)
    71  		case *uint16, *[]uint16:
    72  			return newRLeafU16(leaf, rvar, rctx)
    73  		default:
    74  			rv := rv.Elem()
    75  			switch rv.Kind() {
    76  			case reflect.Array:
    77  				rt, _ := flattenArrayType(rv.Type())
    78  				switch rt.Kind() {
    79  				case reflect.Int16:
    80  					return newRLeafI16(leaf, rvar, rctx)
    81  				case reflect.Uint16:
    82  					return newRLeafU16(leaf, rvar, rctx)
    83  				}
    84  			case reflect.Slice:
    85  				rt, _ := flattenArrayType(rv.Type().Elem())
    86  				switch rt.Kind() {
    87  				case reflect.Int16:
    88  					return newRLeafI16(leaf, rvar, rctx)
    89  				case reflect.Uint16:
    90  					return newRLeafU16(leaf, rvar, rctx)
    91  				}
    92  			}
    93  		}
    94  		panic(fmt.Errorf("rvar mismatch for %T", leaf))
    95  	case *LeafI:
    96  		switch rv := reflect.ValueOf(rvar.Value); rv.Interface().(type) {
    97  		case *int32, *[]int32:
    98  			return newRLeafI32(leaf, rvar, rctx)
    99  		case *uint32, *[]uint32:
   100  			return newRLeafU32(leaf, rvar, rctx)
   101  		default:
   102  			rv := rv.Elem()
   103  			switch rv.Kind() {
   104  			case reflect.Array:
   105  				rt, _ := flattenArrayType(rv.Type())
   106  				switch rt.Kind() {
   107  				case reflect.Int32:
   108  					return newRLeafI32(leaf, rvar, rctx)
   109  				case reflect.Uint32:
   110  					return newRLeafU32(leaf, rvar, rctx)
   111  				}
   112  			case reflect.Slice:
   113  				rt, _ := flattenArrayType(rv.Type().Elem())
   114  				switch rt.Kind() {
   115  				case reflect.Int32:
   116  					return newRLeafI32(leaf, rvar, rctx)
   117  				case reflect.Uint32:
   118  					return newRLeafU32(leaf, rvar, rctx)
   119  				}
   120  			}
   121  		}
   122  		panic(fmt.Errorf("rvar mismatch for %T", leaf))
   123  	case *LeafL:
   124  		switch rv := reflect.ValueOf(rvar.Value); rv.Interface().(type) {
   125  		case *int64, *[]int64:
   126  			return newRLeafI64(leaf, rvar, rctx)
   127  		case *uint64, *[]uint64:
   128  			return newRLeafU64(leaf, rvar, rctx)
   129  		default:
   130  			rv := rv.Elem()
   131  			switch rv.Kind() {
   132  			case reflect.Array:
   133  				rt, _ := flattenArrayType(rv.Type())
   134  				switch rt.Kind() {
   135  				case reflect.Int64:
   136  					return newRLeafI64(leaf, rvar, rctx)
   137  				case reflect.Uint64:
   138  					return newRLeafU64(leaf, rvar, rctx)
   139  				}
   140  			case reflect.Slice:
   141  				rt, _ := flattenArrayType(rv.Type().Elem())
   142  				switch rt.Kind() {
   143  				case reflect.Int64:
   144  					return newRLeafI64(leaf, rvar, rctx)
   145  				case reflect.Uint64:
   146  					return newRLeafU64(leaf, rvar, rctx)
   147  				}
   148  			}
   149  			panic(fmt.Errorf("rvar mismatch for %T", leaf))
   150  		}
   151  	case *LeafG:
   152  		// FIXME(sbinet): should we bite the bullet and generate a whole
   153  		// set of types+funcs for LeafG instead of relying on the
   154  		// assumption that LeafG data has the same underlying layout and size
   155  		// than LeafL ? (ie: sizeof(Long_t) == sizeof(Long64_t))
   156  		return rleafFrom((*LeafL)(unsafe.Pointer(leaf)), rvar, rctx)
   157  	case *LeafF:
   158  		return newRLeafF32(leaf, rvar, rctx)
   159  	case *LeafD:
   160  		return newRLeafF64(leaf, rvar, rctx)
   161  	case *LeafF16:
   162  		return newRLeafF16(leaf, rvar, rctx)
   163  	case *LeafD32:
   164  		return newRLeafD32(leaf, rvar, rctx)
   165  	case *LeafC:
   166  		return newRLeafStr(leaf, rvar, rctx)
   167  
   168  	case *tleafElement:
   169  		return newRLeafElem(leaf, rvar, rctx)
   170  
   171  	case *tleafObject:
   172  		return newRLeafObject(leaf, rvar, rctx)
   173  
   174  	default:
   175  		panic(fmt.Errorf("not implemented %T", leaf))
   176  	}
   177  }
   178  
   179  type rleafObject struct {
   180  	base *tleafObject
   181  	v    rbytes.Unmarshaler
   182  }
   183  
   184  var (
   185  	_ rleaf = (*rleafObject)(nil)
   186  )
   187  
   188  func newRLeafObject(leaf *tleafObject, rvar ReadVar, rctx rleafCtx) rleaf {
   189  	switch {
   190  	case leaf.count != nil:
   191  		panic("not implemented")
   192  	case leaf.len > 1:
   193  		panic("not implemented")
   194  	default:
   195  		return &rleafObject{
   196  			base: leaf,
   197  			v:    reflect.ValueOf(rvar.Value).Interface().(rbytes.Unmarshaler),
   198  		}
   199  	}
   200  }
   201  
   202  func (leaf *rleafObject) Leaf() Leaf { return leaf.base }
   203  
   204  func (leaf *rleafObject) Offset() int64 {
   205  	return int64(leaf.base.Offset())
   206  }
   207  
   208  func (leaf *rleafObject) readFromBuffer(r *rbytes.RBuffer) error {
   209  	if leaf.base.virtual {
   210  		var (
   211  			n     = int(r.ReadU8())
   212  			class = r.ReadCString(n + 1)
   213  		)
   214  		if class != leaf.base.Title() {
   215  			// FIXME(sbinet): we should be able to handle (C++) polymorphism.
   216  			// but in Go, this should translate to interfaces.
   217  			panic(fmt.Errorf(
   218  				"rtree: rleaf object with incompatible class names: got=%q, want=%q",
   219  				class, leaf.base.Title(),
   220  			))
   221  		}
   222  	}
   223  
   224  	return leaf.v.UnmarshalROOT(r)
   225  }
   226  
   227  func newRLeafElem(leaf *tleafElement, rvar ReadVar, rctx rleafCtx) rleaf {
   228  	const kind = rbytes.ObjectWise // FIXME(sbinet): infer from stream?
   229  
   230  	var (
   231  		b         = leaf.branch.(*tbranchElement)
   232  		si        = b.streamer
   233  		err       error
   234  		rstreamer rbytes.RStreamer
   235  	)
   236  
   237  	switch {
   238  	case b.id < 0:
   239  		rstreamer, err = si.NewRStreamer(kind)
   240  	default:
   241  		rstreamer, err = rdict.RStreamerOf(si, int(b.id), kind)
   242  	}
   243  
   244  	if err != nil {
   245  		panic(fmt.Errorf(
   246  			"rtree: could not find read-streamer for leaf=%q (type=%s): %+v",
   247  			leaf.Name(), leaf.TypeName(), err,
   248  		))
   249  	}
   250  	err = rstreamer.(rbytes.Binder).Bind(rvar.Value)
   251  	if err != nil {
   252  		panic(fmt.Errorf("rtree: could not bind read-streamer for leaf=%q (type=%s) to ptr=%T: %w",
   253  			leaf.Name(), leaf.TypeName(), rvar.Value, err,
   254  		))
   255  	}
   256  
   257  	if leaf.count != nil {
   258  		r, ok := rstreamer.(rbytes.Counter)
   259  		if !ok {
   260  			panic(fmt.Errorf(
   261  				"rtree: could not set read-streamer counter for leaf=%q (type=%s): %+v",
   262  				leaf.Name(), leaf.TypeName(), err,
   263  			))
   264  		}
   265  		lc := rctx.rcountLeaf(leaf.count.Name())
   266  		err = r.Count(lc.ivalue)
   267  		if err != nil {
   268  			panic(fmt.Errorf(
   269  				"rtree: could not set read-streamer counter for leaf=%q (type=%s): %+v",
   270  				leaf.Name(), leaf.TypeName(), err,
   271  			))
   272  		}
   273  	}
   274  
   275  	return &rleafElem{
   276  		base:     leaf,
   277  		v:        rvar.Value,
   278  		streamer: rstreamer,
   279  	}
   280  }
   281  
   282  type rleafElem struct {
   283  	base     *tleafElement
   284  	v        any
   285  	n        func() int
   286  	streamer rbytes.RStreamer
   287  }
   288  
   289  func (leaf *rleafElem) Leaf() Leaf { return leaf.base }
   290  
   291  func (leaf *rleafElem) Offset() int64 {
   292  	return int64(leaf.base.Offset())
   293  }
   294  
   295  func (leaf *rleafElem) readFromBuffer(r *rbytes.RBuffer) error {
   296  	return leaf.streamer.RStreamROOT(r)
   297  }
   298  
   299  func (leaf *rleafElem) bindCount() {
   300  	switch v := reflect.ValueOf(leaf.v).Interface().(type) {
   301  	case *int8:
   302  		leaf.n = func() int { return int(*v) }
   303  	case *int16:
   304  		leaf.n = func() int { return int(*v) }
   305  	case *int32:
   306  		leaf.n = func() int { return int(*v) }
   307  	case *int64:
   308  		leaf.n = func() int { return int(*v) }
   309  	case *uint8:
   310  		leaf.n = func() int { return int(*v) }
   311  	case *uint16:
   312  		leaf.n = func() int { return int(*v) }
   313  	case *uint32:
   314  		leaf.n = func() int { return int(*v) }
   315  	case *uint64:
   316  		leaf.n = func() int { return int(*v) }
   317  	default:
   318  		panic(fmt.Errorf("invalid leaf-elem type: %T", v))
   319  	}
   320  }
   321  
   322  func (leaf *rleafElem) ivalue() int {
   323  	return leaf.n()
   324  }
   325  
   326  var (
   327  	_ rleaf = (*rleafElem)(nil)
   328  )
   329  
   330  type rleafCount struct {
   331  	Leaf
   332  	n    func() int
   333  	leaf rleaf
   334  }
   335  
   336  func (l *rleafCount) ivalue() int {
   337  	return l.n()
   338  }
   339  
   340  func (l *rleafCount) imax() int {
   341  	panic("not implemented")
   342  }
   343  
   344  var (
   345  	_ leafCount = (*rleafCount)(nil)
   346  )
   347  
   348  // FIXME(sbinet): directly use reflect.TypeFor[T]().Size()
   349  // instead of this shim function.
   350  // (when Go >= 1.22)
   351  func sizeOfT[T any]() uintptr {
   352  	var t T
   353  	return reflect.TypeOf(t).Size()
   354  }
   355  
   356  func unsafeDecayArray[T any](ptr any) *[]T {
   357  	rv := reflect.ValueOf(ptr).Elem()
   358  	sz := rv.Type().Size() / sizeOfT[T]()
   359  	sli := unsafe.Slice((*T)(unsafe.Pointer(rv.UnsafeAddr())), sz)
   360  	return &sli
   361  }
   362  
   363  func unsafeDecaySliceArray[T any](ptr *[]T, size int) *[]T {
   364  	var sli []T
   365  	if *ptr == nil {
   366  		return &sli
   367  	}
   368  	sli = unsafe.Slice(unsafe.SliceData(*ptr), size)
   369  	return &sli
   370  }