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 }