go-hep.org/x/hep@v0.38.1/groot/rdict/decoder.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 rdict 6 7 import ( 8 "fmt" 9 "reflect" 10 "strings" 11 12 "go-hep.org/x/hep/groot/rbytes" 13 ) 14 15 type decoder struct { 16 r *rbytes.RBuffer 17 si *StreamerInfo 18 kind rbytes.StreamKind 19 rops []rstreamer 20 } 21 22 func newDecoder(r *rbytes.RBuffer, si *StreamerInfo, kind rbytes.StreamKind, ops []rstreamer) (*decoder, error) { 23 return &decoder{r, si, kind, ops}, nil 24 } 25 26 func (dec *decoder) DecodeROOT(ptr any) error { 27 rv := reflect.ValueOf(ptr) 28 if rv.Kind() != reflect.Ptr { 29 return fmt.Errorf("rdict: invalid kind (got=%T, want=pointer)", ptr) 30 } 31 32 var ( 33 typename = dec.si.Name() 34 typevers = int16(dec.si.ClassVersion()) 35 hdr = dec.r.ReadHeader(typename, typevers) 36 ) 37 38 if hdr.Vers != typevers { 39 dec.r.SetErr(fmt.Errorf("rdict: inconsistent ROOT version type=%q (got=%d, want=%d)", 40 typename, hdr.Vers, typevers, 41 )) 42 return dec.r.Err() 43 } 44 45 for i, op := range dec.rops { 46 err := op.rstream(dec.r, ptr) 47 if err != nil { 48 return fmt.Errorf("rdict: could not read element %d from %q: %w", i, typename, err) 49 } 50 } 51 52 dec.r.CheckHeader(hdr) 53 if err := dec.r.Err(); err != nil { 54 return fmt.Errorf("rdict: invalid bytecount for %q: %w", typename, err) 55 } 56 57 return nil 58 } 59 60 var ( 61 _ rbytes.Decoder = (*decoder)(nil) 62 ) 63 64 type rstreamerInfo struct { 65 recv any 66 rops []rstreamer 67 kind rbytes.StreamKind 68 si *StreamerInfo 69 } 70 71 func newRStreamerInfo(si *StreamerInfo, kind rbytes.StreamKind, rops []rstreamer) (*rstreamerInfo, error) { 72 return &rstreamerInfo{ 73 recv: nil, 74 rops: rops, 75 kind: kind, 76 si: si, 77 }, nil 78 } 79 80 func (rr *rstreamerInfo) Bind(recv any) error { 81 rv := reflect.ValueOf(recv) 82 if rv.Kind() != reflect.Ptr { 83 return fmt.Errorf("rdict: invalid kind (got=%T, want=pointer)", recv) 84 } 85 rr.recv = recv 86 if recv, ok := recv.(rbytes.Unmarshaler); ok && rr.kind == rbytes.ObjectWise { 87 // FIXME(sbinet): handle mbr-/obj-wise 88 rr.rops = []rstreamer{{ 89 op: func(r *rbytes.RBuffer, _ any, _ *streamerConfig) error { 90 return recv.UnmarshalROOT(r) 91 }, 92 cfg: nil, 93 }} 94 return nil 95 } 96 if len(rr.rops) == 1 { 97 se := rr.rops[0].cfg.descr.elem 98 if se.Name() == "This" || 99 strings.HasPrefix(se.TypeName(), "vector<") { 100 // binding directly to 'recv'. assume no offset is to be applied 101 rr.rops[0].cfg.offset = -1 102 } 103 } 104 return nil 105 } 106 107 func (rr *rstreamerInfo) RStreamROOT(r *rbytes.RBuffer) error { 108 for i, op := range rr.rops { 109 err := op.rstream(r, rr.recv) 110 if err != nil { 111 typename := rr.si.Name() 112 return fmt.Errorf("rdict: could not read element %d from %q: %w", i, typename, err) 113 } 114 } 115 return nil 116 } 117 118 var ( 119 _ rbytes.RStreamer = (*rstreamerInfo)(nil) 120 _ rbytes.Binder = (*rstreamerInfo)(nil) 121 )