go-hep.org/x/hep@v0.38.1/groot/rdict/object.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 package rdict 6 7 import ( 8 "fmt" 9 "reflect" 10 "strings" 11 12 "go-hep.org/x/hep/groot/rbytes" 13 "go-hep.org/x/hep/groot/root" 14 "go-hep.org/x/hep/groot/rtypes" 15 ) 16 17 var ( 18 cxxNameSanitizer = strings.NewReplacer( 19 "<", "_", 20 ">", "_", 21 ":", "_", 22 ",", "_", 23 " ", "_", 24 ) 25 ) 26 27 func ObjectFrom(si rbytes.StreamerInfo, sictx rbytes.StreamerInfoContext) *Object { 28 return newObjectFrom(si, sictx) 29 } 30 31 // Object wraps a type created from a Streamer and implements the 32 // following interfaces: 33 // - root.Object 34 // - rbytes.RVersioner 35 // - rbytes.Marshaler 36 // - rbytes.Unmarshaler 37 type Object struct { 38 v any 39 40 si *StreamerInfo 41 rvers int16 42 class string 43 } 44 45 func (obj *Object) Class() string { 46 return obj.class 47 } 48 49 func (obj *Object) SetClass(name string) { 50 si, ok := StreamerInfos.Get(name, -1) 51 if !ok { 52 panic(fmt.Errorf("rdict: no streamer for %q", name)) 53 } 54 *obj = *newObjectFrom(si, StreamerInfos) 55 } 56 57 func (obj *Object) String() string { 58 return fmt.Sprintf("%v", obj.v) 59 } 60 61 func (obj *Object) RVersion() int16 { 62 return obj.rvers 63 } 64 65 func (obj *Object) UnmarshalROOT(r *rbytes.RBuffer) error { 66 if r.Err() != nil { 67 return r.Err() 68 } 69 70 dec, err := obj.si.NewDecoder(rbytes.ObjectWise, r) 71 if err != nil { 72 return fmt.Errorf("rdict: could not create decoder for %q: %w", obj.si.Name(), err) 73 } 74 75 err = dec.DecodeROOT(obj.v) 76 if err != nil { 77 return fmt.Errorf("rdict: could not decode %q: %w", obj.si.Name(), err) 78 } 79 80 return r.Err() 81 } 82 83 func (obj *Object) MarshalROOT(w *rbytes.WBuffer) (int, error) { 84 if w.Err() != nil { 85 return 0, w.Err() 86 } 87 88 enc, err := obj.si.NewEncoder(rbytes.ObjectWise, w) 89 if err != nil { 90 return 0, fmt.Errorf("rdict: could not create encoder for %q: %w", obj.si.Name(), err) 91 } 92 93 pos := w.Pos() 94 95 err = enc.EncodeROOT(obj.v) 96 if err != nil { 97 return 0, fmt.Errorf("rdict: could not encode %q: %w", obj.si.Name(), err) 98 } 99 100 return int(w.Pos() - pos), w.Err() 101 } 102 103 func newObjectFrom(si rbytes.StreamerInfo, sictx rbytes.StreamerInfoContext) *Object { 104 err := si.BuildStreamers() 105 if err != nil { 106 panic(fmt.Errorf("rdict: could not build streamers: %w", err)) 107 } 108 109 rt, err := TypeFromSI(sictx, si) 110 if err != nil { 111 panic(fmt.Errorf("rdict: could not build object type: %w", err)) 112 } 113 114 recv := reflect.New(rt) 115 obj := &Object{ 116 v: recv.Interface(), 117 si: si.(*StreamerInfo), 118 rvers: int16(si.ClassVersion()), 119 class: si.Name(), 120 } 121 return obj 122 } 123 124 var ( 125 _ root.Object = (*Object)(nil) 126 _ rbytes.RVersioner = (*Object)(nil) 127 _ rbytes.Marshaler = (*Object)(nil) 128 _ rbytes.Unmarshaler = (*Object)(nil) 129 ) 130 131 func init() { 132 { 133 f := func() reflect.Value { 134 o := &Object{class: "*rdict.Object"} 135 return reflect.ValueOf(o) 136 } 137 rtypes.Factory.Add("*rdict.Object", f) 138 } 139 }