go-hep.org/x/hep@v0.40.0/groot/gen.rtree.go (about)

     1  // Copyright ©2018 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  //go:build ignore
     6  
     7  package main
     8  
     9  import (
    10  	"fmt"
    11  	"log"
    12  	"os"
    13  	"reflect"
    14  	"text/template"
    15  
    16  	"go-hep.org/x/hep/groot/internal/genroot"
    17  	"go-hep.org/x/hep/groot/root"
    18  )
    19  
    20  func main() {
    21  	genLeaves()
    22  	genRLeaves()
    23  }
    24  
    25  func genLeaves() {
    26  	fname := "./rtree/leaf_gen.go"
    27  	year := genroot.ExtractYear(fname)
    28  	f, err := os.Create(fname)
    29  	if err != nil {
    30  		log.Fatal(err)
    31  	}
    32  	defer f.Close()
    33  
    34  	genroot.GenImports(year, "rtree", f,
    35  		"fmt",
    36  		"reflect",
    37  		"strings",
    38  		"unsafe", // FIXME(sbinet): needed for signed/unsigned handling
    39  		"",
    40  		"go-hep.org/x/hep/groot/root",
    41  		"go-hep.org/x/hep/groot/rbase",
    42  		"go-hep.org/x/hep/groot/rbytes",
    43  		"go-hep.org/x/hep/groot/rdict",
    44  		"go-hep.org/x/hep/groot/rmeta",
    45  		"go-hep.org/x/hep/groot/rtypes",
    46  		"go-hep.org/x/hep/groot/rvers",
    47  	)
    48  
    49  	for i, typ := range []struct {
    50  		Name       string
    51  		Type       string
    52  		Kind       string
    53  		UKind      string
    54  		LenType    int
    55  		GoLenType  int
    56  		DoUnsigned bool
    57  		RFunc      string
    58  		RFuncArray string
    59  		ResizeFunc string
    60  		WFunc      string
    61  		WFuncArray string
    62  		RangeType  string
    63  		RRangeFunc string
    64  		WRangeFunc string
    65  		Count      bool
    66  
    67  		WithStreamerElement bool   // for TLeaf{F16,D32}
    68  		Meta                string // name of rmeta.Enum to use (for TLeaf{F16,D32})
    69  	}{
    70  		{
    71  			Name:       "LeafO",
    72  			Type:       "bool",
    73  			Kind:       "reflect.Bool",
    74  			LenType:    1,
    75  			GoLenType:  int(reflect.TypeFor[bool]().Size()),
    76  			RFunc:      "r.ReadBool()",
    77  			RFuncArray: "r.ReadArrayBool",
    78  			ResizeFunc: "rbytes.ResizeBool",
    79  			WFunc:      "w.WriteBool",
    80  			WFuncArray: "w.WriteArrayBool",
    81  		},
    82  		{
    83  			Name:       "LeafB",
    84  			Type:       "int8",
    85  			Kind:       "reflect.Int8",
    86  			UKind:      "reflect.Uint8",
    87  			LenType:    1,
    88  			GoLenType:  int(reflect.TypeFor[int8]().Size()),
    89  			DoUnsigned: true,
    90  			RFunc:      "r.ReadI8()",
    91  			RFuncArray: "r.ReadArrayI8",
    92  			ResizeFunc: "rbytes.ResizeI8",
    93  			WFunc:      "w.WriteI8",
    94  			WFuncArray: "w.WriteArrayI8",
    95  			Count:      true,
    96  		},
    97  		{
    98  			Name:       "LeafS",
    99  			Type:       "int16",
   100  			Kind:       "reflect.Int16",
   101  			UKind:      "reflect.Uint16",
   102  			LenType:    2,
   103  			GoLenType:  int(reflect.TypeFor[int16]().Size()),
   104  			DoUnsigned: true,
   105  			RFunc:      "r.ReadI16()",
   106  			RFuncArray: "r.ReadArrayI16",
   107  			ResizeFunc: "rbytes.ResizeI16",
   108  			WFunc:      "w.WriteI16",
   109  			WFuncArray: "w.WriteArrayI16",
   110  			Count:      true,
   111  		},
   112  		{
   113  			Name:       "LeafI",
   114  			Type:       "int32",
   115  			Kind:       "reflect.Int32",
   116  			UKind:      "reflect.Uint32",
   117  			LenType:    4,
   118  			GoLenType:  int(reflect.TypeFor[int32]().Size()),
   119  			DoUnsigned: true,
   120  			RFunc:      "r.ReadI32()",
   121  			RFuncArray: "r.ReadArrayI32",
   122  			ResizeFunc: "rbytes.ResizeI32",
   123  			WFunc:      "w.WriteI32",
   124  			WFuncArray: "w.WriteArrayI32",
   125  			Count:      true,
   126  		},
   127  		{
   128  			Name:       "LeafL",
   129  			Type:       "int64",
   130  			Kind:       "reflect.Int64",
   131  			UKind:      "reflect.Uint64",
   132  			LenType:    8,
   133  			GoLenType:  int(reflect.TypeFor[int64]().Size()),
   134  			DoUnsigned: true,
   135  			RFunc:      "r.ReadI64()",
   136  			RFuncArray: "r.ReadArrayI64",
   137  			ResizeFunc: "rbytes.ResizeI64",
   138  			WFunc:      "w.WriteI64",
   139  			WFuncArray: "w.WriteArrayI64",
   140  			Count:      true,
   141  		},
   142  		{
   143  			Name:       "LeafG",
   144  			Type:       "int64",
   145  			Kind:       "reflect.Int64",
   146  			UKind:      "reflect.Uint64",
   147  			LenType:    8,
   148  			GoLenType:  int(reflect.TypeFor[int64]().Size()),
   149  			DoUnsigned: true,
   150  			RFunc:      "r.ReadI64()",
   151  			RFuncArray: "r.ReadArrayI64",
   152  			ResizeFunc: "rbytes.ResizeI64",
   153  			WFunc:      "w.WriteI64",
   154  			WFuncArray: "w.WriteArrayI64",
   155  			Count:      true,
   156  		},
   157  		{
   158  			Name:       "LeafF",
   159  			Type:       "float32",
   160  			Kind:       "reflect.Float32",
   161  			LenType:    4,
   162  			GoLenType:  int(reflect.TypeFor[float32]().Size()),
   163  			RFunc:      "r.ReadF32()",
   164  			RFuncArray: "r.ReadArrayF32",
   165  			ResizeFunc: "rbytes.ResizeF32",
   166  			WFunc:      "w.WriteF32",
   167  			WFuncArray: "w.WriteArrayF32",
   168  		},
   169  		{
   170  			Name:       "LeafD",
   171  			Type:       "float64",
   172  			Kind:       "reflect.Float64",
   173  			LenType:    8,
   174  			GoLenType:  int(reflect.TypeFor[float64]().Size()),
   175  			RFunc:      "r.ReadF64()",
   176  			RFuncArray: "r.ReadArrayF64",
   177  			ResizeFunc: "rbytes.ResizeF64",
   178  			WFunc:      "w.WriteF64",
   179  			WFuncArray: "w.WriteArrayF64",
   180  		},
   181  		{
   182  			Name:                "LeafF16",
   183  			Type:                "root.Float16",
   184  			Kind:                "reflect.Float32",
   185  			LenType:             4,
   186  			GoLenType:           int(reflect.TypeFor[root.Float16]().Size()),
   187  			RFunc:               "r.ReadF16(leaf.elm)",
   188  			RFuncArray:          "r.ReadArrayF16",
   189  			ResizeFunc:          "rbytes.ResizeF16",
   190  			WFunc:               "w.WriteF16",
   191  			WFuncArray:          "w.WriteArrayF16",
   192  			WithStreamerElement: true,
   193  			Meta:                "rmeta.Float16",
   194  		},
   195  		{
   196  			Name:                "LeafD32",
   197  			Type:                "root.Double32",
   198  			Kind:                "reflect.Float64",
   199  			LenType:             8,
   200  			GoLenType:           int(reflect.TypeFor[root.Double32]().Size()),
   201  			RFunc:               "r.ReadD32(leaf.elm)",
   202  			RFuncArray:          "r.ReadArrayD32",
   203  			ResizeFunc:          "rbytes.ResizeD32",
   204  			WFunc:               "w.WriteD32",
   205  			WFuncArray:          "w.WriteArrayD32",
   206  			WithStreamerElement: true,
   207  			Meta:                "rmeta.Double32",
   208  		},
   209  		{
   210  			Name:       "LeafC",
   211  			Type:       "string",
   212  			Kind:       "reflect.String",
   213  			LenType:    1,
   214  			GoLenType:  int(reflect.TypeFor[string]().Size()),
   215  			RFunc:      "r.ReadString()",
   216  			RFuncArray: "r.ReadArrayString",
   217  			ResizeFunc: "rbytes.ResizeStr",
   218  			WFunc:      "w.WriteString",
   219  			WFuncArray: "w.WriteArrayString",
   220  			RangeType:  "int32",
   221  			RRangeFunc: "r.ReadI32()",
   222  			WRangeFunc: "w.WriteI32",
   223  		},
   224  	} {
   225  		if i > 0 {
   226  			fmt.Fprintf(f, "\n")
   227  		}
   228  		if typ.RangeType == "" {
   229  			typ.RangeType = typ.Type
   230  			typ.RRangeFunc = typ.RFunc
   231  			typ.WRangeFunc = typ.WFunc
   232  		}
   233  		tmpl := template.Must(template.New(typ.Name).Parse(leafTmpl))
   234  		err = tmpl.Execute(f, typ)
   235  		if err != nil {
   236  			log.Fatalf("error executing template for %q: %v\n", typ.Name, err)
   237  		}
   238  	}
   239  
   240  	err = f.Close()
   241  	if err != nil {
   242  		log.Fatal(err)
   243  	}
   244  	genroot.GoFmt(f)
   245  }
   246  
   247  const leafTmpl = `// {{.Name}} implements ROOT T{{.Name}}
   248  type {{.Name}} struct {
   249  	rvers int16
   250  	tleaf
   251  	ptr *{{.Type}}
   252  	sli *[]{{.Type}}
   253  	min {{.RangeType}}
   254  	max {{.RangeType}}
   255  {{- if .WithStreamerElement}}
   256  	elm rbytes.StreamerElement
   257  {{- end}}
   258  }
   259  
   260  {{- if .WithStreamerElement}}
   261  func new{{.Name}}(b Branch, name string, shape []int, unsigned bool, count Leaf, elm rbytes.StreamerElement) *{{.Name}} {
   262  	const etype = {{.LenType}}
   263  	var lcnt leafCount
   264  	if count != nil {
   265  		lcnt = count.(leafCount)
   266  	}
   267  	return &{{.Name}}{
   268  		rvers: rvers.{{.Name}},
   269  		tleaf: newLeaf(name, shape, etype, 0, false, unsigned, lcnt, b),
   270  		elm:   elm,
   271  	}
   272  }
   273  {{- else}}
   274  func new{{.Name}}(b Branch, name string, shape []int, unsigned bool, count Leaf) *{{.Name}} {
   275  	const etype = {{.LenType}}
   276  	var lcnt leafCount
   277  	if count != nil {
   278  		lcnt = count.(leafCount)
   279  	}
   280  	return &{{.Name}}{
   281  		rvers: rvers.{{.Name}},
   282  		tleaf: newLeaf(name, shape, etype, 0, false, unsigned, lcnt, b),
   283  	}
   284  }
   285  {{- end}}
   286  
   287  // Class returns the ROOT class name.
   288  func (leaf *{{.Name}}) Class() string {
   289  	return "T{{.Name}}"
   290  }
   291  
   292  // Minimum returns the minimum value of the leaf.
   293  func (leaf *{{.Name}}) Minimum() {{.RangeType}} {
   294  	return leaf.min
   295  }
   296  
   297  // Maximum returns the maximum value of the leaf.
   298  func (leaf *{{.Name}}) Maximum() {{.RangeType}} {
   299  	return leaf.max
   300  }
   301  
   302  // Kind returns the leaf's kind.
   303  func (leaf *{{.Name}}) Kind() reflect.Kind {
   304  {{- if .DoUnsigned}}
   305  	if leaf.IsUnsigned() {
   306  		return {{.UKind}}
   307  	}
   308  	return {{.Kind}}
   309  {{- else}}
   310  	return {{.Kind}}
   311  {{- end}}
   312  }
   313  
   314  // Type returns the leaf's type.
   315  func (leaf *{{.Name}}) Type() reflect.Type {
   316  {{- if .DoUnsigned}}
   317  	if leaf.IsUnsigned() {
   318  		return reflect.TypeFor[u{{.Type}}]()
   319  	}
   320  	return reflect.TypeFor[{{.Type}}]()
   321  {{- else}}
   322  	return reflect.TypeFor[{{.Type}}]()
   323  {{- end}}
   324  }
   325  
   326  {{- if .Count}}
   327  // ivalue returns the first leaf value as int
   328  func (leaf *{{.Name}}) ivalue() int {
   329  	return int(*leaf.ptr)
   330  }
   331  
   332  // imax returns the leaf maximum value as int
   333  func (leaf *{{.Name}}) imax() int {
   334  	return int(leaf.max)
   335  }
   336  {{- end}}
   337  
   338  func (leaf *{{.Name}}) TypeName() string {
   339  {{- if .DoUnsigned}}
   340  	if leaf.IsUnsigned() {
   341  		return "u{{.Type}}"
   342  	}
   343  	return "{{.Type}}"
   344  {{- else}}
   345  	return "{{.Type}}"
   346  {{- end}}
   347  }
   348  
   349  func (leaf *{{.Name}}) MarshalROOT(w *rbytes.WBuffer) (int, error) {
   350  	if w.Err() != nil {
   351  		return 0, w.Err()
   352  	}
   353  
   354  	hdr := w.WriteHeader(leaf.Class(), leaf.rvers)
   355  	w.WriteObject(&leaf.tleaf)
   356  {{- if .WithStreamerElement}}
   357  	{{.WRangeFunc}}(leaf.min, leaf.elm)
   358  	{{.WRangeFunc}}(leaf.max, leaf.elm)
   359  {{- else}}
   360  	{{.WRangeFunc}}(leaf.min)
   361  	{{.WRangeFunc}}(leaf.max)
   362  {{- end}}
   363  
   364  	return w.SetHeader(hdr)
   365  }
   366  
   367  func (leaf *{{.Name}}) UnmarshalROOT(r *rbytes.RBuffer) error {
   368  	if r.Err() != nil {
   369  		return r.Err()
   370  	}
   371  
   372  	hdr := r.ReadHeader(leaf.Class(), leaf.RVersion())
   373  	leaf.rvers = hdr.Vers
   374  
   375  	r.ReadObject(&leaf.tleaf)
   376  
   377  	leaf.min = {{.RRangeFunc}}
   378  	leaf.max = {{.RRangeFunc}}
   379  
   380  {{if .WithStreamerElement}}
   381  	if strings.Contains(leaf.Title(), "[") {
   382  		elm := rdict.Element{
   383  			Name:   *rbase.NewNamed(fmt.Sprintf("%s_Element", leaf.Name()), leaf.Title()),
   384  			Offset: 0,
   385  			Type:   {{.Meta}},
   386  		}.New()
   387  		leaf.elm = &elm
   388  	}
   389  {{- end}}
   390  
   391  	r.CheckHeader(hdr)
   392  	return r.Err()
   393  }
   394  
   395  func (leaf *{{.Name}}) readFromBuffer(r *rbytes.RBuffer) error {
   396  	if r.Err() != nil {
   397  		return r.Err()
   398  	}
   399  
   400  	if leaf.count == nil && leaf.ptr != nil {
   401  		*leaf.ptr = {{.RFunc}}
   402  	} else {
   403              if leaf.count != nil {
   404                  n := leaf.count.ivalue()
   405                  max := leaf.count.imax()
   406                  if n > max {
   407                          n = max
   408                  }
   409  				nn := leaf.tleaf.len * n
   410  				*leaf.sli = {{.ResizeFunc}}(*leaf.sli, nn)
   411  {{- if .WithStreamerElement}}
   412                  {{.RFuncArray}}(*leaf.sli, leaf.elm)
   413  {{- else}}
   414                  {{.RFuncArray}}(*leaf.sli)
   415  {{- end}}
   416              } else {
   417  				nn := leaf.tleaf.len
   418  				*leaf.sli = {{.ResizeFunc}}(*leaf.sli, nn)
   419  {{- if .WithStreamerElement}}
   420  				{{.RFuncArray}}(*leaf.sli, leaf.elm)
   421  {{- else}}
   422  				{{.RFuncArray}}(*leaf.sli)
   423  {{- end}}
   424              }
   425      }
   426      return r.Err()
   427  }
   428  
   429  func (leaf *{{.Name}}) unsafeDecayArray(ptr any) any {
   430  	rv := reflect.ValueOf(ptr).Elem()
   431  	sz := rv.Type().Size() / {{.GoLenType}}
   432  	sli := unsafe.Slice((*{{.Type}})(unsafe.Pointer(rv.UnsafeAddr())), sz)
   433  	return &sli
   434  }
   435  
   436  func (leaf *{{.Name}}) setAddress(ptr any) error {
   437  	if ptr == nil {
   438  		return leaf.setAddress(newValue(leaf))
   439  	}
   440  
   441      if rv := reflect.Indirect(reflect.ValueOf(ptr)); rv.Kind() == reflect.Array {
   442  		sli := leaf.unsafeDecayArray(ptr)
   443  		switch sli := sli.(type) {
   444  		case *[]{{.Type}}:
   445  			return leaf.setAddress(sli)
   446  {{- if .DoUnsigned}}
   447  		case *[]u{{.Type}}:
   448  			return leaf.setAddress(sli)
   449  {{- end}}
   450  		default:
   451  			panic(fmt.Errorf("invalid ptr type %T (leaf=%s|%T)", ptr, leaf.Name(), leaf))
   452  		}
   453      }
   454  
   455  	switch v := ptr.(type) {
   456      case *{{.Type}}:
   457  		leaf.ptr = v
   458      case *[]{{.Type}}:
   459  		leaf.sli = v
   460  		if *v == nil {
   461  			*leaf.sli = make([]{{.Type}}, 0)
   462  		}
   463  {{- if .DoUnsigned}}
   464      case *u{{.Type}}:
   465  		leaf.ptr = (*{{.Type}})(unsafe.Pointer(v))
   466      case *[]u{{.Type}}:
   467  		leaf.sli = (*[]{{.Type}})(unsafe.Pointer(v))
   468  		if *v == nil {
   469  			*leaf.sli = make([]{{.Type}}, 0)
   470  		}
   471  {{- end}}
   472  	default:
   473  		panic(fmt.Errorf("invalid ptr type %T (leaf=%s|%T)", v, leaf.Name(), leaf))
   474  	}
   475  	return nil
   476  }
   477  
   478  func (leaf *{{.Name}}) writeToBuffer(w *rbytes.WBuffer) (int, error) {
   479  	if w.Err() != nil {
   480  		return 0, w.Err()
   481  	}
   482  
   483  	var nbytes int
   484  	switch {
   485  	case leaf.ptr != nil:
   486  {{- if .WithStreamerElement}}
   487  		{{.WFunc}}(*leaf.ptr, leaf.elm)
   488  {{- else}}
   489  		{{.WFunc}}(*leaf.ptr)
   490  {{- end}}
   491  {{- if eq .Name "LeafC"}}
   492  		sz := len(*leaf.ptr)
   493  		nbytes += sz
   494  		if v := int32(sz); v >= leaf.max {
   495  			leaf.max = v+1
   496  		}
   497  		if sz >= leaf.tleaf.len {
   498  			leaf.tleaf.len = sz+1
   499  		}
   500  {{- else if eq .Name "LeafO"}}
   501  		nbytes += leaf.tleaf.etype
   502  {{- else}}
   503  		nbytes += leaf.tleaf.etype
   504  		if v := *leaf.ptr; v > leaf.max {
   505  			leaf.max = v
   506  		}
   507  {{- end}}
   508  	case leaf.count != nil:
   509  		n := leaf.count.ivalue()
   510          max := leaf.count.imax()
   511          if n > max {
   512  			n = max
   513  		}
   514  		end := leaf.tleaf.len*n
   515  {{- if .WithStreamerElement}}
   516  		{{.WFuncArray}}((*leaf.sli)[:end], leaf.elm)
   517  {{- else}}
   518  		{{.WFuncArray}}((*leaf.sli)[:end])
   519  {{- end}}
   520  		nbytes += leaf.tleaf.etype * end
   521  	default:
   522  {{- if .WithStreamerElement}}
   523  		{{.WFuncArray}}((*leaf.sli)[:leaf.tleaf.len], leaf.elm)
   524  {{- else}}
   525  		{{.WFuncArray}}((*leaf.sli)[:leaf.tleaf.len])
   526  {{- end}}
   527  		nbytes += leaf.tleaf.etype * leaf.tleaf.len
   528  	}
   529  
   530  	return nbytes, w.Err()
   531  }
   532  
   533  func init() {
   534  	f := func() reflect.Value {
   535  		o := &{{.Name}}{}
   536  		return reflect.ValueOf(o)
   537  	}
   538  	rtypes.Factory.Add("T{{.Name}}", f)
   539  }
   540  
   541  var (
   542  	_ root.Object        = (*{{.Name}})(nil)
   543  	_ root.Named         = (*{{.Name}})(nil)
   544  	_ Leaf               = (*{{.Name}})(nil)
   545  	_ rbytes.Marshaler   = (*{{.Name}})(nil)
   546  	_ rbytes.Unmarshaler = (*{{.Name}})(nil)
   547  )
   548  `
   549  
   550  func genRLeaves() {
   551  	fname := "./rtree/rleaf_gen.go"
   552  	year := genroot.ExtractYear(fname)
   553  	f, err := os.Create(fname)
   554  	if err != nil {
   555  		log.Fatal(err)
   556  	}
   557  	defer f.Close()
   558  
   559  	type Kind string
   560  	const (
   561  		Val = Kind("Val")
   562  		Arr = Kind("Arr")
   563  		Sli = Kind("Sli")
   564  	)
   565  
   566  	genroot.GenImports(year, "rtree", f,
   567  		"reflect",
   568  		"unsafe", // for unsafeDecayArrayXXX
   569  		"",
   570  		"go-hep.org/x/hep/groot/rbytes",
   571  		"go-hep.org/x/hep/groot/root",
   572  	)
   573  
   574  	for i, typ := range []struct {
   575  		Name  string
   576  		Base  string
   577  		Type  string
   578  		Size  int
   579  		Kind  Kind
   580  		Func  string
   581  		Count bool
   582  
   583  		WithStreamerElement bool // for TLeaf{F16,D32}
   584  	}{
   585  		{
   586  			Name: "Bool",
   587  			Base: "LeafO",
   588  			Type: "bool",
   589  			Size: int(reflect.TypeFor[bool]().Size()),
   590  		},
   591  		{
   592  			Name:  "I8",
   593  			Base:  "LeafB",
   594  			Type:  "int8",
   595  			Size:  int(reflect.TypeFor[int8]().Size()),
   596  			Count: true,
   597  		},
   598  		{
   599  			Name:  "I16",
   600  			Base:  "LeafS",
   601  			Type:  "int16",
   602  			Size:  int(reflect.TypeFor[int16]().Size()),
   603  			Count: true,
   604  		},
   605  		{
   606  			Name:  "I32",
   607  			Base:  "LeafI",
   608  			Type:  "int32",
   609  			Size:  int(reflect.TypeFor[int32]().Size()),
   610  			Count: true,
   611  		},
   612  		{
   613  			Name:  "I64",
   614  			Base:  "LeafL",
   615  			Type:  "int64",
   616  			Size:  int(reflect.TypeFor[int64]().Size()),
   617  			Count: true,
   618  		},
   619  		{
   620  			Name:  "U8",
   621  			Base:  "LeafB",
   622  			Type:  "uint8",
   623  			Size:  int(reflect.TypeFor[uint8]().Size()),
   624  			Count: true,
   625  		},
   626  		{
   627  			Name:  "U16",
   628  			Base:  "LeafS",
   629  			Type:  "uint16",
   630  			Size:  int(reflect.TypeFor[uint16]().Size()),
   631  			Count: true,
   632  		},
   633  		{
   634  			Name:  "U32",
   635  			Base:  "LeafI",
   636  			Type:  "uint32",
   637  			Size:  int(reflect.TypeFor[uint32]().Size()),
   638  			Count: true,
   639  		},
   640  		{
   641  			Name:  "U64",
   642  			Base:  "LeafL",
   643  			Type:  "uint64",
   644  			Size:  int(reflect.TypeFor[uint64]().Size()),
   645  			Count: true,
   646  		},
   647  		{
   648  			Name: "F32",
   649  			Base: "LeafF",
   650  			Type: "float32",
   651  			Size: int(reflect.TypeFor[float32]().Size()),
   652  		},
   653  		{
   654  			Name: "F64",
   655  			Base: "LeafD",
   656  			Type: "float64",
   657  			Size: int(reflect.TypeFor[float64]().Size()),
   658  		},
   659  		{
   660  			Name: "D32",
   661  			Base: "LeafD32",
   662  			Type: "root.Double32",
   663  			Size: int(reflect.TypeFor[root.Double32]().Size()),
   664  
   665  			WithStreamerElement: true,
   666  		},
   667  		{
   668  			Name: "F16",
   669  			Base: "LeafF16",
   670  			Type: "root.Float16",
   671  			Size: int(reflect.TypeFor[root.Float16]().Size()),
   672  
   673  			WithStreamerElement: true,
   674  		},
   675  		{
   676  			Name: "Str",
   677  			Base: "LeafC",
   678  			Type: "string",
   679  			Size: int(reflect.TypeFor[string]().Size()),
   680  		},
   681  	} {
   682  		for j, kind := range []Kind{Val, Arr, Sli} {
   683  			if i > 0 || j > 0 {
   684  				fmt.Fprintf(f, "\n")
   685  			}
   686  			typ.Kind = kind
   687  			switch typ.Name {
   688  			case "Str":
   689  				typ.Func = "String"
   690  			default:
   691  				typ.Func = typ.Name
   692  			}
   693  
   694  			tmpl := template.Must(template.New(typ.Name).Parse(rleafTmpl))
   695  			err = tmpl.Execute(f, typ)
   696  			if err != nil {
   697  				log.Fatalf("error executing template for %q: %v\n", typ.Name, err)
   698  			}
   699  		}
   700  	}
   701  
   702  	err = f.Close()
   703  	if err != nil {
   704  		log.Fatal(err)
   705  	}
   706  	genroot.GoFmt(f)
   707  }
   708  
   709  const rleafTmpl = `// rleaf{{.Kind}}{{.Name}} implements rleaf for ROOT T{{.Base}}
   710  type rleaf{{.Kind}}{{.Name}} struct {
   711  	base *{{.Base}}
   712  {{- if eq .Kind "Val" }}
   713  	v *{{.Type}}
   714  {{- else if eq .Kind "Arr" }}
   715  	v []{{.Type}}
   716  {{- else if eq .Kind "Sli" }}
   717  	n   func() int
   718  	v   *[]{{.Type}}
   719  	set func() // reslice underlying slice
   720  {{- end}}
   721  {{- if .WithStreamerElement}}
   722  	elm rbytes.StreamerElement
   723  {{- end}}
   724  }
   725  
   726  {{- if eq .Kind "Val"}}
   727  func newRLeaf{{.Name}}(leaf *{{.Base}}, rvar ReadVar, rctx rleafCtx) rleaf {
   728  	switch {
   729  	case leaf.count != nil:
   730  		switch len(leaf.Shape()) {
   731  		case 0:
   732  			slice := reflect.ValueOf(rvar.Value).Interface().(*[]{{.Type}})
   733  			if *slice == nil {
   734  				*slice = make([]{{.Type}}, 0, rleafDefaultSliceCap)
   735  			}
   736  			return &rleafSli{{.Name}}{
   737  				base: leaf,
   738  				n:    rctx.rcountFunc(leaf.count.Name()),
   739  				v:    slice,
   740  				set:  func() {},
   741  			}
   742  		default:
   743  			sz := 1
   744  			for _, v := range leaf.Shape() {
   745  				sz *= v
   746  			}
   747  			sli := reflect.ValueOf(rvar.Value).Elem()
   748  			ptr := (*[]{{.Type}})(unsafe.Pointer(sli.UnsafeAddr()))
   749  			hdr := unsafeDecaySliceArray[{{.Type}}](ptr, sz)
   750  			if *hdr == nil {
   751  				*hdr = make([]{{.Type}}, 0, rleafDefaultSliceCap*sz)
   752  			}
   753  			rleaf := &rleafSli{{.Name}}{
   754  				base: leaf,
   755  				n:    rctx.rcountFunc(leaf.count.Name()),
   756  				v:    hdr,
   757  			}
   758  			rhdr := reflect.ValueOf(hdr).Elem()
   759  			rptr := reflect.ValueOf(ptr).Elem()
   760  
   761  			// alias slices
   762  			rptr.Set(rhdr)
   763  
   764  			rleaf.set = func() {
   765  				n := rleaf.n()
   766  				rptr.SetLen(n)
   767  			}
   768  
   769  			return rleaf
   770  }
   771  
   772  	case leaf.len > 1:
   773  		return &rleafArr{{.Name}}{
   774  			base: leaf,
   775  			v:    *unsafeDecayArray[{{.Type}}](rvar.Value),
   776  		}
   777  
   778  	default:
   779  		return &rleafVal{{.Name}}{
   780  			base: leaf,
   781  			v:    reflect.ValueOf(rvar.Value).Interface().(*{{.Type}}),
   782  		}
   783  	}
   784  }
   785  {{- end}}
   786  
   787  func (leaf *rleaf{{.Kind}}{{.Name}}) Leaf() Leaf { return leaf.base }
   788  
   789  func (leaf *rleaf{{.Kind}}{{.Name}}) Offset() int64 {
   790  	return int64(leaf.base.Offset())
   791  }
   792  
   793  {{if eq .Kind "Val"}}
   794  {{if .Count}}
   795  func (leaf *rleaf{{.Kind}}{{.Name}}) ivalue() int { return int(*leaf.v) }
   796  {{- end}}
   797  {{- end}}
   798  
   799  {{if .WithStreamerElement}}
   800  func (leaf *rleaf{{.Kind}}{{.Name}}) readFromBuffer(r *rbytes.RBuffer) error {
   801  {{- if eq .Kind "Val" }}
   802  	*leaf.v = r.Read{{.Func}}(leaf.elm)
   803  {{- else if eq .Kind "Arr" }}
   804  	r.ReadArray{{.Func}}(leaf.v, leaf.elm)
   805  {{- else if eq .Kind "Sli" }}
   806  	n := leaf.base.tleaf.len * leaf.n()
   807  	sli := rbytes.Resize{{.Name}}(*leaf.v, n)
   808  	r.ReadArray{{.Func}}(sli, leaf.elm)
   809  	*leaf.v = sli
   810  	leaf.set()
   811  {{- end}}
   812  	return r.Err()
   813  }
   814  {{else}}
   815  func (leaf *rleaf{{.Kind}}{{.Name}}) readFromBuffer(r *rbytes.RBuffer) error {
   816  {{- if eq .Kind "Val" }}
   817  	*leaf.v = r.Read{{.Func}}()
   818  {{- else if eq .Kind "Arr" }}
   819  	r.ReadArray{{.Func}}(leaf.v)
   820  {{- else if eq .Kind "Sli" }}
   821  	n := leaf.base.tleaf.len * leaf.n()
   822  	sli := rbytes.Resize{{.Name}}(*leaf.v, n)
   823  	r.ReadArray{{.Func}}(sli)
   824  	*leaf.v = sli
   825  	leaf.set()
   826  {{- end}}
   827  	return r.Err()
   828  }
   829  {{- end}}
   830  
   831  var (
   832  	_ rleaf = (*rleaf{{.Kind}}{{.Name}})(nil)
   833  )
   834  `