func TypeFromSI(ctx rbytes.StreamerInfoContext, si rbytes.StreamerInfo) (reflect.Type, error) {
	name := si.Name()
	if rtypes.Factory.HasKey(name) {
		fct := rtypes.Factory.Get(name)
		v := fct()
		return v.Type().Elem(), nil
	}

	switch {
	case name == "string", name == "std::string":
		if len(si.Elements()) == 0 {
			// fix for old (v=2) streamer for string
			sinfo := si.(*StreamerInfo)
			sinfo.elems = append(sinfo.elems, &StreamerSTLstring{
				StreamerSTL: StreamerSTL{
					StreamerElement: Element{
						Name:   *rbase.NewNamed("This", ""),
						Type:   rmeta.STLstring,
						Size:   32,
						MaxIdx: [5]int32{0, 0, 0, 0, 0},
						EName:  "string",
					}.New(),
					vtype: rmeta.ESTLType(rmeta.STLstring),
					ctype: rmeta.STLstring,
				},
			})
		}
		return gotypes[reflect.String], nil

	case strings.HasPrefix(name, "vector<"),
		strings.HasPrefix(name, "map<"): // FIXME(sbinet): handle other std::containers?
		var (
			se      = si.Elements()[0]
			rt, err = TypeFromSE(ctx, se)
		)
		if err != nil {
			return nil, fmt.Errorf(
				"rdict: could not build element %q type for %q: %w",
				se.Name(), si.Name(), err,
			)
		}
		return rt, nil
	}

	fields := make([]reflect.StructField, 0, len(si.Elements()))
	for _, se := range si.Elements() {
		rt, err := TypeFromSE(ctx, se)
		if err != nil {
			return nil, fmt.Errorf(
				"rdict: could not build element %q type for %q: %w",
				se.Name(), si.Name(), err,
			)
		}
		et := se.Title()
		if !strings.HasPrefix(et, "[") {
			et = ""
		}
		if rt.Kind() == reflect.Array {
			et = ndimsFromType(rt)
		}
		ft := reflect.StructField{
			Name: "ROOT_" + cxxNameSanitizer.Replace(se.Name()),
			Type: rt,
			Tag:  reflect.StructTag(fmt.Sprintf("groot:%q", se.Name()+et)),
		}
		fields = append(fields, ft)
	}

	return reflect.StructOf(fields), nil
}
// TypeFromSI returns a Go type corresponding to the provided StreamerInfo.
// TypeFromSI first reaches out to the known groot types (via groot/rtypes) and
// then resorts to building a new type with reflect.
TypeFromSI returns a Go type corresponding to the provided StreamerInfo.
TypeFromSI first reaches out to the known groot types (via groot/rtypes) and
then resorts to building a new type with reflect.
// TypeFromSI returns a Go type corresponding to the provided StreamerInfo . // TypeFromSI first reaches out to the known groot types ( via groot / rtypes ) and // then resorts to building a new type with reflect .
func TypeFromSI(ctx rbytes.StreamerInfoContext, si rbytes.StreamerInfo) (reflect.Type, error) {
	name := si.Name()
	if rtypes.Factory.HasKey(name) {
		fct := rtypes.Factory.Get(name)
		v := fct()
		return v.Type().Elem(), nil
	}
	switch {
	case name == "string", name == "std::string":
		if len(si.Elements()) == 0 {
			sinfo := si.(*StreamerInfo)
			sinfo.elems = append(sinfo.elems, &StreamerSTLstring{
				StreamerSTL: StreamerSTL{
					StreamerElement: Element{
						Name:   *rbase.NewNamed("This", ""),
						Type:   rmeta.STLstring,
						Size:   32,
						MaxIdx: [5]int32{0, 0, 0, 0, 0},
						EName:  "string",
					}.New(),
					vtype: rmeta.ESTLType(rmeta.STLstring),
					ctype: rmeta.STLstring,
				},
			})
		}
		return gotypes[reflect.String], nil
	case strings.HasPrefix(name, "vector<"),
		strings.HasPrefix(name, "map<"): 
		var (
			se      = si.Elements()[0]
			rt, err = TypeFromSE(ctx, se)
		)
		if err != nil {
			return nil, fmt.Errorf(
				"rdict: could not build element %q type for %q: %w",
				se.Name(), si.Name(), err,
			)
		}
		return rt, nil
	}
	fields := make([]reflect.StructField, 0, len(si.Elements()))
	for _, se := range si.Elements() {
		rt, err := TypeFromSE(ctx, se)
		if err != nil {
			return nil, fmt.Errorf(
				"rdict: could not build element %q type for %q: %w",
				se.Name(), si.Name(), err,
			)
		}
		et := se.Title()
		if !strings.HasPrefix(et, "[") {
			et = ""
		}
		if rt.Kind() == reflect.Array {
			et = ndimsFromType(rt)
		}
		ft := reflect.StructField{
			Name: "ROOT_" + cxxNameSanitizer.Replace(se.Name()),
			Type: rt,
			Tag:  reflect.StructTag(fmt.Sprintf("groot:%q", se.Name()+et)),
		}
		fields = append(fields, ft)
	}
	return reflect.StructOf(fields), nil
}
func TypeFromSI ( ctx rbytes . StreamerInfoContext , si rbytes . StreamerInfo ) ( reflect . Type , error ) { name := si . Name ( ) if rtypes . Factory . HasKey ( name ) { fct := rtypes . Factory . Get ( name ) v := fct ( ) return v . Type ( ) . Elem ( ) , nil } switch { case name == " " , name == " " : if len ( si . Elements ( ) ) == 0 { sinfo := si . ( * StreamerInfo ) sinfo . elems = append ( sinfo . elems , & StreamerSTLstring { StreamerSTL : StreamerSTL { StreamerElement : Element { Name : * rbase . NewNamed ( " " , " " ) , Type : rmeta . STLstring , Size : 32 , MaxIdx : [ 5 ] int32 { 0 , 0 , 0 , 0 , 0 } , EName : " " , } . New ( ) , vtype : rmeta . ESTLType ( rmeta . STLstring ) , ctype : rmeta . STLstring , } , } ) } return gotypes [ reflect . String ] , nil case strings . HasPrefix ( name , " " ) , strings . HasPrefix ( name , " " ) : var ( se = si . Elements ( ) [ 0 ] rt , err = TypeFromSE ( ctx , se ) ) if err != nil { return nil , fmt . Errorf ( " " , se . Name ( ) , si . Name ( ) , err , ) } return rt , nil } fields := make ( [ ] reflect . StructField , 0 , len ( si . Elements ( ) ) ) for _ , se := range si . Elements ( ) { rt , err := TypeFromSE ( ctx , se ) if err != nil { return nil , fmt . Errorf ( " " , se . Name ( ) , si . Name ( ) , err , ) } et := se . Title ( ) if ! strings . HasPrefix ( et , " " ) { et = " " } if rt . Kind ( ) == reflect . Array { et = ndimsFromType ( rt ) } ft := reflect . StructField { Name : " " + cxxNameSanitizer . Replace ( se . Name ( ) ) , Type : rt , Tag : reflect . StructTag ( fmt . Sprintf ( " " , se . Name ( ) + et ) ) , } fields = append ( fields , ft ) } return reflect . StructOf ( fields ) , nil }
TypeFromSI returns a Go type corresponding to the provided StreamerInfo.
TypeFromSI returns a Go type corresponding to the provided StreamerInfo .
// fix for old (v=2) streamer for string // FIXME(sbinet): handle other std::containers?