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

     1  // Copyright ©2017 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  	"regexp"
    11  	"strconv"
    12  	"strings"
    13  
    14  	"go-hep.org/x/hep/groot/rbase"
    15  	"go-hep.org/x/hep/groot/rbytes"
    16  	"go-hep.org/x/hep/groot/rdict"
    17  	"go-hep.org/x/hep/groot/rmeta"
    18  	"go-hep.org/x/hep/groot/root"
    19  	"go-hep.org/x/hep/groot/rtypes"
    20  	"go-hep.org/x/hep/groot/rvers"
    21  )
    22  
    23  type tleaf struct {
    24  	named    rbase.Named
    25  	len      int  // number of fixed length elements in the leaf's data.
    26  	etype    int  // number of bytes for this data type
    27  	offset   int  // offset in ClonesArray object
    28  	hasrange bool // whether the leaf has a range
    29  	unsigned bool // whether the leaf holds unsigned data (uint8, uint16, uint32 or uint64)
    30  	shape    []int
    31  	count    leafCount // leaf count if variable length
    32  	branch   Branch    // supporting branch of this leaf
    33  }
    34  
    35  func newLeaf(name string, shape []int, etype, offset int, hasrange, unsigned bool, count leafCount, b Branch) tleaf {
    36  	var (
    37  		nelems = 1
    38  		title  = new(strings.Builder)
    39  	)
    40  
    41  	title.WriteString(name)
    42  	switch {
    43  	case count != nil:
    44  		fmt.Fprintf(title, "[%s]", count.Name())
    45  	default:
    46  		for _, dim := range shape {
    47  			nelems *= dim
    48  			fmt.Fprintf(title, "[%d]", dim)
    49  		}
    50  	}
    51  	return tleaf{
    52  		named:    *rbase.NewNamed(name, title.String()),
    53  		len:      nelems,
    54  		etype:    etype,
    55  		offset:   offset,
    56  		hasrange: hasrange,
    57  		unsigned: unsigned,
    58  		shape:    shape,
    59  		count:    count,
    60  		branch:   b,
    61  	}
    62  }
    63  
    64  func (*tleaf) RVersion() int16 {
    65  	return rvers.Leaf
    66  }
    67  
    68  // Name returns the name of the instance
    69  func (leaf *tleaf) Name() string {
    70  	return leaf.named.Name()
    71  }
    72  
    73  // Title returns the title of the instance
    74  func (leaf *tleaf) Title() string {
    75  	return leaf.named.Title()
    76  }
    77  
    78  func (leaf *tleaf) Class() string {
    79  	return "TLeaf"
    80  }
    81  
    82  func (leaf *tleaf) Shape() []int {
    83  	return leaf.shape
    84  }
    85  
    86  func (leaf *tleaf) setBranch(b Branch) {
    87  	leaf.branch = b
    88  }
    89  
    90  func (leaf *tleaf) Branch() Branch {
    91  	return leaf.branch
    92  }
    93  
    94  func (leaf *tleaf) HasRange() bool {
    95  	return leaf.hasrange
    96  }
    97  
    98  func (leaf *tleaf) IsUnsigned() bool {
    99  	return leaf.unsigned
   100  }
   101  
   102  func (leaf *tleaf) LeafCount() Leaf {
   103  	return leaf.count
   104  }
   105  
   106  func (leaf *tleaf) Len() int {
   107  	if leaf.count != nil {
   108  		// variable length array
   109  		n := leaf.count.ivalue()
   110  		max := leaf.count.imax()
   111  		if n > max {
   112  			n = max
   113  		}
   114  		return leaf.len * n
   115  	}
   116  	return leaf.len
   117  }
   118  
   119  func (leaf *tleaf) LenType() int {
   120  	return leaf.etype
   121  }
   122  
   123  func (leaf *tleaf) Offset() int {
   124  	return leaf.offset
   125  }
   126  
   127  func (leaf *tleaf) Kind() reflect.Kind {
   128  	panic("not implemented: " + leaf.Name())
   129  }
   130  
   131  func (leaf *tleaf) Type() reflect.Type {
   132  	panic("not implemented: " + leaf.Name())
   133  }
   134  
   135  func (leaf *tleaf) readFromBuffer(r *rbytes.RBuffer) error {
   136  	panic("not implemented: " + leaf.Name())
   137  }
   138  
   139  func (leaf *tleaf) setAddress(ptr any) error {
   140  	panic("not implemented: " + leaf.Name())
   141  }
   142  
   143  func (leaf *tleaf) writeToBuffer(w *rbytes.WBuffer) (int, error) {
   144  	panic("not implemented: " + leaf.Name())
   145  }
   146  
   147  func (leaf *tleaf) TypeName() string {
   148  	panic("not implemented: " + leaf.Name())
   149  }
   150  
   151  func (leaf *tleaf) MarshalROOT(w *rbytes.WBuffer) (int, error) {
   152  	if w.Err() != nil {
   153  		return 0, w.Err()
   154  	}
   155  
   156  	hdr := w.WriteHeader(leaf.Class(), leaf.RVersion())
   157  	w.WriteObject(&leaf.named)
   158  
   159  	w.WriteI32(int32(leaf.len))
   160  	w.WriteI32(int32(leaf.etype))
   161  	w.WriteI32(int32(leaf.offset))
   162  	w.WriteBool(leaf.hasrange)
   163  	w.WriteBool(leaf.unsigned)
   164  	w.WriteObjectAny(leaf.count)
   165  	return w.SetHeader(hdr)
   166  }
   167  
   168  func (leaf *tleaf) UnmarshalROOT(r *rbytes.RBuffer) error {
   169  	if r.Err() != nil {
   170  		return r.Err()
   171  	}
   172  
   173  	hdr := r.ReadHeader(leaf.Class(), leaf.RVersion())
   174  
   175  	r.ReadObject(&leaf.named)
   176  	leaf.shape = leafDims(leaf.Title())
   177  	leaf.len = int(r.ReadI32())
   178  	leaf.etype = int(r.ReadI32())
   179  	leaf.offset = int(r.ReadI32())
   180  	leaf.hasrange = r.ReadBool()
   181  	leaf.unsigned = r.ReadBool()
   182  
   183  	leaf.count = nil
   184  	ptr := r.ReadObjectAny()
   185  	if ptr != nil {
   186  		leaf.count = ptr.(leafCount)
   187  	}
   188  
   189  	if leaf.len == 0 {
   190  		leaf.len = 1
   191  	}
   192  
   193  	r.CheckHeader(hdr)
   194  	return r.Err()
   195  }
   196  
   197  func (leaf *tleaf) canGenerateOffsetArray() bool {
   198  	return leaf.count != nil
   199  }
   200  
   201  func (leaf *tleaf) computeOffsetArray(base, nevts int) []int32 {
   202  	o := make([]int32, nevts)
   203  	if leaf.count == nil {
   204  		return o
   205  	}
   206  
   207  	var (
   208  		hdr           = tleafHdrSize
   209  		origEntry     = maxI64(leaf.branch.getReadEntry(), 0) // -1 indicates to start at the beginning
   210  		origLeafEntry = leaf.count.Branch().getReadEntry()
   211  		sz            int
   212  		offset        = int32(base)
   213  	)
   214  	for i := range nevts {
   215  		o[i] = offset
   216  		leaf.count.Branch().getEntry(origEntry + int64(i))
   217  		sz = leaf.count.ivalue()
   218  		offset += int32(leaf.etype*sz + hdr)
   219  	}
   220  	leaf.count.Branch().getEntry(origLeafEntry)
   221  
   222  	return o
   223  }
   224  
   225  // tleafObject is a Leaf for a general object derived from Object.
   226  type tleafObject struct {
   227  	tleaf
   228  	virtual bool
   229  	typ     reflect.Type
   230  }
   231  
   232  func (*tleafObject) RVersion() int16 {
   233  	return rvers.LeafObject
   234  }
   235  
   236  func (leaf *tleafObject) Class() string {
   237  	return "TLeafObject"
   238  }
   239  
   240  func (leaf *tleafObject) Type() reflect.Type {
   241  	return leaf.typ
   242  }
   243  
   244  func (leaf *tleafObject) MarshalROOT(w *rbytes.WBuffer) (int, error) {
   245  	if w.Err() != nil {
   246  		return 0, w.Err()
   247  	}
   248  
   249  	hdr := w.WriteHeader(leaf.Class(), leaf.RVersion())
   250  	w.WriteObject(&leaf.tleaf)
   251  	w.WriteBool(leaf.virtual)
   252  
   253  	return w.SetHeader(hdr)
   254  }
   255  
   256  func (leaf *tleafObject) UnmarshalROOT(r *rbytes.RBuffer) error {
   257  	if r.Err() != nil {
   258  		return r.Err()
   259  	}
   260  
   261  	hdr := r.ReadHeader(leaf.Class(), leaf.RVersion())
   262  
   263  	if hdr.Vers < 4 {
   264  		panic(fmt.Errorf(
   265  			"rtree: TLeafObject %q with version [%v] is not supported (too old)",
   266  			leaf.Name(),
   267  			hdr.Vers,
   268  		))
   269  	}
   270  
   271  	r.ReadObject(&leaf.tleaf)
   272  	leaf.virtual = r.ReadBool()
   273  
   274  	if !rtypes.Factory.HasKey(leaf.Title()) {
   275  		return fmt.Errorf("rtree: could not find type %q for TLeafObject %q", leaf.Title(), leaf.Name())
   276  	}
   277  	leaf.typ = rtypes.Factory.Get(leaf.Title())().Type().Elem()
   278  
   279  	r.CheckHeader(hdr)
   280  	return r.Err()
   281  }
   282  
   283  const (
   284  	tleafHdrSize        = 0
   285  	tleafElementHdrSize = 1
   286  )
   287  
   288  // tleafElement is a Leaf for a general object derived from Object.
   289  type tleafElement struct {
   290  	rvers int16
   291  	tleaf
   292  	id    int32 // element serial number in fInfo
   293  	ltype int32 // leaf type
   294  
   295  	ptr       any
   296  	src       reflect.Value
   297  	rstreamer rbytes.RStreamer
   298  	wstreamer rbytes.WStreamer
   299  	streamers []rbytes.StreamerElement
   300  }
   301  
   302  func (*tleafElement) RVersion() int16 {
   303  	return rvers.LeafElement
   304  }
   305  
   306  func (leaf *tleafElement) Class() string {
   307  	return "TLeafElement"
   308  }
   309  
   310  func (leaf *tleafElement) ivalue() int {
   311  	return int(leaf.src.Int())
   312  }
   313  
   314  func (leaf *tleafElement) imax() int {
   315  	panic("not implemented")
   316  }
   317  
   318  func (leaf *tleafElement) Kind() reflect.Kind {
   319  	return leaf.src.Kind()
   320  }
   321  
   322  func (leaf *tleafElement) Type() reflect.Type {
   323  	return leaf.src.Type()
   324  }
   325  
   326  func (leaf *tleafElement) TypeName() string {
   327  	name := leaf.src.Type().Name()
   328  	if name == "" {
   329  		panic(fmt.Errorf("rtree: invalid typename for leaf %q", leaf.Name()))
   330  	}
   331  	return name
   332  }
   333  
   334  func (leaf *tleafElement) MarshalROOT(w *rbytes.WBuffer) (int, error) {
   335  	if w.Err() != nil {
   336  		return 0, w.Err()
   337  	}
   338  
   339  	hdr := w.WriteHeader(leaf.Class(), leaf.rvers)
   340  	w.WriteObject(&leaf.tleaf)
   341  	w.WriteI32(leaf.id)
   342  	w.WriteI32(leaf.ltype)
   343  
   344  	return w.SetHeader(hdr)
   345  }
   346  
   347  func (leaf *tleafElement) UnmarshalROOT(r *rbytes.RBuffer) error {
   348  	if r.Err() != nil {
   349  		return r.Err()
   350  	}
   351  
   352  	hdr := r.ReadHeader(leaf.Class(), leaf.RVersion())
   353  	leaf.rvers = hdr.Vers
   354  
   355  	r.ReadObject(&leaf.tleaf)
   356  	leaf.id = r.ReadI32()
   357  	leaf.ltype = r.ReadI32()
   358  
   359  	r.CheckHeader(hdr)
   360  	return r.Err()
   361  }
   362  
   363  func (leaf *tleafElement) readFromBuffer(r *rbytes.RBuffer) error {
   364  	if r.Err() != nil {
   365  		return r.Err()
   366  	}
   367  
   368  	if leaf.rstreamer == nil {
   369  		panic(fmt.Errorf("rtree: nil streamer (leaf: %s)", leaf.Name()))
   370  	}
   371  
   372  	err := leaf.rstreamer.RStreamROOT(r)
   373  	if err != nil {
   374  		return err
   375  	}
   376  
   377  	return nil
   378  }
   379  
   380  func (leaf *tleafElement) setAddress(ptr any) error {
   381  	leaf.ptr = ptr
   382  	leaf.src = reflect.ValueOf(leaf.ptr).Elem()
   383  
   384  	if leaf.rstreamer != nil {
   385  		return leaf.setReadAddress(ptr)
   386  	}
   387  
   388  	if leaf.wstreamer != nil {
   389  		return leaf.setWriteAddress(ptr)
   390  	}
   391  
   392  	return fmt.Errorf("rtree: leaf %q is neither read nor write", leaf.Name())
   393  }
   394  
   395  func (leaf *tleafElement) setReadAddress(ptr any) error {
   396  	err := leaf.rstreamer.(rbytes.Binder).Bind(ptr)
   397  	if err != nil {
   398  		return fmt.Errorf("rtree: could not bind read-streamer for leaf=%q (type=%s) to ptr=%T: %w",
   399  			leaf.Name(), leaf.TypeName(), leaf.ptr, err,
   400  		)
   401  	}
   402  	if leaf.count != nil {
   403  		r, ok := leaf.rstreamer.(rbytes.Counter)
   404  		if !ok {
   405  			return fmt.Errorf(
   406  				"rtree: could not set read-streamer counter for leaf=%q (type=%s)",
   407  				leaf.Name(), leaf.TypeName(),
   408  			)
   409  		}
   410  		err = r.Count(leaf.count.ivalue)
   411  		if err != nil {
   412  			return fmt.Errorf(
   413  				"rtree: could not set read-streamer counter for leaf=%q (type=%s): %w",
   414  				leaf.Name(), leaf.TypeName(), err,
   415  			)
   416  		}
   417  	}
   418  	return nil
   419  }
   420  
   421  func (leaf *tleafElement) setWriteAddress(ptr any) error {
   422  	err := leaf.wstreamer.(rbytes.Binder).Bind(ptr)
   423  	if err != nil {
   424  		return fmt.Errorf("rtree: could not bind write-streamer for leaf=%q (type=%s) to ptr=%T: %w",
   425  			leaf.Name(), leaf.TypeName(), leaf.ptr, err,
   426  		)
   427  	}
   428  	if leaf.count != nil {
   429  		w, ok := leaf.wstreamer.(rbytes.Counter)
   430  		if !ok {
   431  			return fmt.Errorf(
   432  				"rtree: could not set write-streamer counter for leaf=%q (type=%s)",
   433  				leaf.Name(), leaf.TypeName(),
   434  			)
   435  		}
   436  		err = w.Count(leaf.count.ivalue)
   437  		if err != nil {
   438  			return fmt.Errorf(
   439  				"rtree: could not set write-streamer counter for leaf=%q (type=%s): %w",
   440  				leaf.Name(), leaf.TypeName(), err,
   441  			)
   442  		}
   443  	}
   444  	return nil
   445  }
   446  
   447  func (leaf *tleafElement) writeToBuffer(w *rbytes.WBuffer) (int, error) {
   448  	if w.Err() != nil {
   449  		return 0, w.Err()
   450  	}
   451  
   452  	if leaf.wstreamer == nil {
   453  		panic(fmt.Errorf("rtree: nil write-streamer (leaf: %s)", leaf.Name()))
   454  	}
   455  
   456  	pos := w.Pos()
   457  	err := leaf.wstreamer.WStreamROOT(w)
   458  	return int(w.Pos() - pos), err
   459  }
   460  
   461  func (leaf *tleafElement) canGenerateOffsetArray() bool {
   462  	return leaf.count != nil && leaf.tleaf.etype != 0
   463  }
   464  
   465  func (leaf *tleafElement) computeOffsetArray(base, nevts int) []int32 {
   466  	o := make([]int32, nevts)
   467  	if leaf.count == nil {
   468  		return o
   469  	}
   470  
   471  	var (
   472  		hdr           = tleafElementHdrSize
   473  		origEntry     = maxI64(leaf.branch.getReadEntry(), 0) // -1 indicates to start at the beginning
   474  		origLeafEntry = leaf.count.Branch().getReadEntry()
   475  		sz            int
   476  		offset        = int32(base)
   477  	)
   478  	for i := range nevts {
   479  		o[i] = offset
   480  		leaf.count.Branch().getEntry(origEntry + int64(i))
   481  		sz = leaf.count.ivalue()
   482  		offset += int32(leaf.etype*sz + hdr)
   483  	}
   484  	leaf.count.Branch().getEntry(origLeafEntry)
   485  
   486  	return o
   487  }
   488  
   489  func init() {
   490  	{
   491  		f := func() reflect.Value {
   492  			o := &tleaf{}
   493  			return reflect.ValueOf(o)
   494  		}
   495  		rtypes.Factory.Add("TLeaf", f)
   496  	}
   497  	{
   498  		f := func() reflect.Value {
   499  			o := &tleafObject{}
   500  			return reflect.ValueOf(o)
   501  		}
   502  		rtypes.Factory.Add("TLeafObject", f)
   503  	}
   504  	{
   505  		f := func() reflect.Value {
   506  			o := &tleafElement{}
   507  			return reflect.ValueOf(o)
   508  		}
   509  		rtypes.Factory.Add("TLeafElement", f)
   510  	}
   511  }
   512  
   513  var (
   514  	reLeafDims = regexp.MustCompile(`\w*?\[(\d*)\]+?`)
   515  )
   516  
   517  func leafDims(s string) []int {
   518  	out := reLeafDims.FindAllStringSubmatch(s, -1)
   519  	if len(out) == 0 {
   520  		return nil
   521  	}
   522  
   523  	dims := make([]int, len(out))
   524  	for i := range out {
   525  		v := out[i][1]
   526  		switch v {
   527  		case "":
   528  			dims[i] = -1 // variable size
   529  		default:
   530  			dim, err := strconv.Atoi(v)
   531  			if err != nil {
   532  				panic(fmt.Errorf("could not infer leaf array dimension: %w", err))
   533  			}
   534  			dims[i] = dim
   535  		}
   536  	}
   537  
   538  	return dims
   539  }
   540  
   541  func gotypeToROOTTypeCode(rt reflect.Type) string {
   542  	switch rt.Kind() {
   543  	case reflect.Bool:
   544  		return "O"
   545  	case reflect.String:
   546  		return "C"
   547  	case reflect.Int8:
   548  		return "B"
   549  	case reflect.Int16:
   550  		return "S"
   551  	case reflect.Int32:
   552  		return "I"
   553  	case reflect.Int64:
   554  		return "L"
   555  	case reflect.Uint8:
   556  		return "b"
   557  	case reflect.Uint16:
   558  		return "s"
   559  	case reflect.Uint32:
   560  		return "i"
   561  	case reflect.Uint64:
   562  		return "l"
   563  	case reflect.Float32:
   564  		if rt == reflect.TypeOf(root.Float16(0)) {
   565  			return "f"
   566  		}
   567  		return "F"
   568  	case reflect.Float64:
   569  		if rt == reflect.TypeOf(root.Double32(0)) {
   570  			return "d"
   571  		}
   572  		return "D"
   573  	case reflect.Array:
   574  		return gotypeToROOTTypeCode(rt.Elem())
   575  	case reflect.Slice:
   576  		return gotypeToROOTTypeCode(rt.Elem())
   577  	}
   578  	panic("impossible")
   579  }
   580  
   581  func newLeafFromWVar(w *wtree, b Branch, v WriteVar, lvl int, cfg wopt) (Leaf, error) {
   582  	const (
   583  		signed   = false
   584  		unsigned = true
   585  	)
   586  
   587  	var (
   588  		rv        = reflect.Indirect(reflect.ValueOf(v.Value))
   589  		rt, shape = flattenArrayType(rv.Type())
   590  		kind      = rt.Kind()
   591  		leaf      Leaf
   592  		count     leafCount
   593  		addLeaf   func(leaf Leaf)
   594  	)
   595  
   596  	switch b := b.(type) {
   597  	case *tbranch:
   598  		addLeaf = func(leaf Leaf) {
   599  			b.leaves = append(b.leaves, leaf)
   600  			w.ttree.leaves = append(w.ttree.leaves, leaf)
   601  		}
   602  	case *tbranchElement:
   603  		addLeaf = func(leaf Leaf) {
   604  			if _, ok := leaf.(*tleafElement); !ok {
   605  				lb, ltyp := asLeafBase(leaf)
   606  
   607  				if b.bup != nil {
   608  					lb.named.SetName(b.bup.Name() + "." + lb.Name())
   609  					lb.named.SetTitle(b.bup.Name() + "." + lb.Title())
   610  				}
   611  				leaf = &tleafElement{
   612  					rvers: rvers.LeafElement,
   613  					tleaf: *lb,
   614  					id:    -1, // FIXME(sbinet): infer correct index
   615  					ltype: int32(ltyp),
   616  				}
   617  			}
   618  
   619  			b.leaves = append(b.leaves, leaf)
   620  			w.ttree.leaves = append(w.ttree.leaves, leaf)
   621  		}
   622  	}
   623  
   624  	switch kind {
   625  	case reflect.Slice:
   626  		lc := b.Leaf(v.Count)
   627  		switch lc {
   628  		case nil:
   629  			// write as vector<T>.
   630  			const (
   631  				offset   = 0
   632  				hasrange = false
   633  				unsigned = false
   634  			)
   635  			base := newLeaf(v.Name, nil, int(rt.Size()), offset, hasrange, unsigned, count, b)
   636  			leaf := &tleafElement{
   637  				rvers: rvers.LeafElement,
   638  				tleaf: base,
   639  				id:    -1, // FIXME(sbinet): create proper serial number
   640  				ltype: 2,  // FIXME(sbinet)
   641  				ptr:   v.Value,
   642  				src:   reflect.ValueOf(v.Value),
   643  			}
   644  			si := rdict.StreamerOf(w.ttree.f, reflect.TypeOf(v.Value).Elem())
   645  
   646  			var err error
   647  			leaf.wstreamer, err = si.NewWStreamer(rbytes.ObjectWise)
   648  			if err != nil {
   649  				return nil, fmt.Errorf("could not create w-streamer for leaf %q: %w", v.Name, err)
   650  			}
   651  
   652  			err = leaf.setAddress(v.Value)
   653  			if err != nil {
   654  				return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   655  			}
   656  
   657  			addLeaf(leaf)
   658  			return leaf, nil
   659  
   660  		default:
   661  			lcc, ok := lc.(leafCount)
   662  			if !ok {
   663  				return nil, fmt.Errorf(
   664  					"leaf count %q from branch %q for slice (name=%q, type=%T) is not a LeafCount",
   665  					v.Count, b.Name(), v.Name, v.Value,
   666  				)
   667  			}
   668  			count = lcc
   669  			kind = rt.Elem().Kind()
   670  		}
   671  
   672  	case reflect.Struct:
   673  		const (
   674  			offset   = 0
   675  			hasrange = false
   676  			unsigned = false
   677  		)
   678  		base := newLeaf(v.Name, nil, int(rt.Size()), offset, hasrange, unsigned, count, b)
   679  		leaf := &tleafElement{
   680  			rvers: rvers.LeafElement,
   681  			tleaf: base,
   682  			id:    -1, // FIXME(sbinet): create proper serial number
   683  			ltype: -1, // FIXME(sbinet)
   684  			ptr:   v.Value,
   685  			src:   reflect.ValueOf(v.Value),
   686  		}
   687  		si := rdict.StreamerOf(w.ttree.f, reflect.TypeOf(v.Value).Elem())
   688  		wstreamer, err := si.NewWStreamer(rbytes.ObjectWise)
   689  		if err != nil {
   690  			return nil, fmt.Errorf("could not create w-streamer for leaf %q: %w", v.Name, err)
   691  		}
   692  		leaf.wstreamer = wstreamer
   693  
   694  		err = leaf.setAddress(v.Value)
   695  		if err != nil {
   696  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   697  		}
   698  		addLeaf(leaf)
   699  		return leaf, nil
   700  	}
   701  
   702  	switch kind {
   703  	case reflect.Bool:
   704  		leaf = newLeafO(b, v.Name, shape, false, count)
   705  		err := leaf.setAddress(v.Value)
   706  		if err != nil {
   707  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   708  		}
   709  		addLeaf(leaf)
   710  
   711  	case reflect.Uint8:
   712  		leaf = newLeafB(b, v.Name, shape, unsigned, count)
   713  		err := leaf.setAddress(v.Value)
   714  		if err != nil {
   715  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   716  		}
   717  		addLeaf(leaf)
   718  
   719  	case reflect.Uint16:
   720  		leaf = newLeafS(b, v.Name, shape, unsigned, count)
   721  		err := leaf.setAddress(v.Value)
   722  		if err != nil {
   723  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   724  		}
   725  		addLeaf(leaf)
   726  
   727  	case reflect.Uint32:
   728  		leaf = newLeafI(b, v.Name, shape, unsigned, count)
   729  		err := leaf.setAddress(v.Value)
   730  		if err != nil {
   731  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   732  		}
   733  		addLeaf(leaf)
   734  
   735  	case reflect.Uint64:
   736  		leaf = newLeafL(b, v.Name, shape, unsigned, count)
   737  		err := leaf.setAddress(v.Value)
   738  		if err != nil {
   739  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   740  		}
   741  		addLeaf(leaf)
   742  
   743  	case reflect.Int8:
   744  		leaf = newLeafB(b, v.Name, shape, signed, count)
   745  		err := leaf.setAddress(v.Value)
   746  		if err != nil {
   747  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   748  		}
   749  		addLeaf(leaf)
   750  
   751  	case reflect.Int16:
   752  		leaf = newLeafS(b, v.Name, shape, signed, count)
   753  		err := leaf.setAddress(v.Value)
   754  		if err != nil {
   755  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   756  		}
   757  		addLeaf(leaf)
   758  
   759  	case reflect.Int32:
   760  		leaf = newLeafI(b, v.Name, shape, signed, count)
   761  		err := leaf.setAddress(v.Value)
   762  		if err != nil {
   763  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   764  		}
   765  		addLeaf(leaf)
   766  
   767  	case reflect.Int64:
   768  		leaf = newLeafL(b, v.Name, shape, signed, count)
   769  		err := leaf.setAddress(v.Value)
   770  		if err != nil {
   771  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   772  		}
   773  		addLeaf(leaf)
   774  
   775  	case reflect.Float32:
   776  		switch rt {
   777  		case reflect.TypeOf(float32(0)), reflect.TypeOf([]float32(nil)):
   778  			leaf = newLeafF(b, v.Name, shape, signed, count)
   779  			err := leaf.setAddress(v.Value)
   780  			if err != nil {
   781  				return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   782  			}
   783  			addLeaf(leaf)
   784  
   785  		case reflect.TypeOf(root.Float16(0)), reflect.TypeOf([]root.Float16(nil)):
   786  			leaf = newLeafF16(b, v.Name, shape, signed, count, nil)
   787  			err := leaf.setAddress(v.Value)
   788  			if err != nil {
   789  				return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   790  			}
   791  			addLeaf(leaf)
   792  
   793  		default:
   794  			panic(fmt.Errorf("invalid type %T", v.Value))
   795  		}
   796  	case reflect.Float64:
   797  		switch rt {
   798  		case reflect.TypeOf(float64(0)), reflect.TypeOf([]float64(nil)):
   799  			leaf = newLeafD(b, v.Name, shape, signed, count)
   800  			err := leaf.setAddress(v.Value)
   801  			if err != nil {
   802  				return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   803  			}
   804  			addLeaf(leaf)
   805  
   806  		case reflect.TypeOf(root.Double32(0)), reflect.TypeOf([]root.Double32(nil)):
   807  			leaf = newLeafD32(b, v.Name, shape, signed, count, nil)
   808  			err := leaf.setAddress(v.Value)
   809  			if err != nil {
   810  				return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   811  			}
   812  			addLeaf(leaf)
   813  
   814  		default:
   815  			panic(fmt.Errorf("invalid type %T", v.Value))
   816  		}
   817  	case reflect.String:
   818  		leaf = newLeafC(b, v.Name, shape, signed, count)
   819  		err := leaf.setAddress(v.Value)
   820  		if err != nil {
   821  			return nil, fmt.Errorf("could not set leaf address for %q: %w", v.Name, err)
   822  		}
   823  		addLeaf(leaf)
   824  
   825  	default:
   826  		return nil, fmt.Errorf("rtree: invalid write-var (name=%q) type %T", v.Name, v.Value)
   827  	}
   828  
   829  	return leaf, nil
   830  }
   831  
   832  func asLeafBase(leaf Leaf) (*tleaf, rmeta.Enum) {
   833  	switch leaf := leaf.(type) {
   834  	case *LeafO:
   835  		return &leaf.tleaf, rmeta.Bool
   836  	case *LeafB:
   837  		return &leaf.tleaf, rmeta.Int8
   838  	case *LeafS:
   839  		return &leaf.tleaf, rmeta.Int16
   840  	case *LeafI:
   841  		return &leaf.tleaf, rmeta.Int32
   842  	case *LeafL:
   843  		return &leaf.tleaf, rmeta.Int64
   844  	case *LeafF:
   845  		return &leaf.tleaf, rmeta.Float32
   846  	case *LeafD:
   847  		return &leaf.tleaf, rmeta.Float64
   848  	case *LeafF16:
   849  		return &leaf.tleaf, rmeta.Float16
   850  	case *LeafD32:
   851  		return &leaf.tleaf, rmeta.Double32
   852  	case *LeafC:
   853  		return &leaf.tleaf, rmeta.CharStar // FIXME(sbinet): rmeta.Char?
   854  	default:
   855  		panic(fmt.Errorf("rtree: invalid leaf type %T", leaf))
   856  	}
   857  }
   858  
   859  var (
   860  	_ root.Object        = (*tleaf)(nil)
   861  	_ root.Named         = (*tleaf)(nil)
   862  	_ Leaf               = (*tleaf)(nil)
   863  	_ rbytes.Marshaler   = (*tleaf)(nil)
   864  	_ rbytes.Unmarshaler = (*tleaf)(nil)
   865  
   866  	_ root.Object        = (*tleafObject)(nil)
   867  	_ root.Named         = (*tleafObject)(nil)
   868  	_ Leaf               = (*tleafObject)(nil)
   869  	_ rbytes.Marshaler   = (*tleafObject)(nil)
   870  	_ rbytes.Unmarshaler = (*tleafObject)(nil)
   871  
   872  	_ root.Object        = (*tleafElement)(nil)
   873  	_ root.Named         = (*tleafElement)(nil)
   874  	_ Leaf               = (*tleafElement)(nil)
   875  	_ rbytes.Marshaler   = (*tleafElement)(nil)
   876  	_ rbytes.Unmarshaler = (*tleafElement)(nil)
   877  )