go-hep.org/x/hep@v0.38.1/groot/rbase/ref.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 rbase 6 7 import ( 8 "fmt" 9 "reflect" 10 11 "github.com/hashicorp/go-uuid" 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 "go-hep.org/x/hep/groot/rvers" 16 ) 17 18 var ( 19 gPID = ProcessID{ 20 named: *NewNamed("ProcessID0", mustGenUUID()), 21 objs: make(map[uint32]root.Object), 22 } 23 ) 24 25 func mustGenUUID() string { 26 id, err := uuid.GenerateUUID() 27 if err != nil { 28 panic(fmt.Errorf("groot/rbase: could not generate UUID: %+v", err)) 29 } 30 return id 31 } 32 33 // Ref implements a persistent link to a root.Object. 34 type Ref struct { 35 obj Object 36 pid *ProcessID 37 } 38 39 func (*Ref) RVersion() int16 { 40 return rvers.Ref 41 } 42 43 func (*Ref) Class() string { return "TRef" } 44 func (*Ref) Name() string { return "TRef" } 45 func (*Ref) Title() string { return "Persistent Reference link to a TObject" } 46 47 func (ref *Ref) UID() uint32 { 48 return ref.obj.UID() 49 } 50 51 func (ref *Ref) String() string { 52 return fmt.Sprintf("Ref{id:%d}", ref.obj.ID) 53 } 54 55 // Object returns the root.Object being referenced by this Ref. 56 func (ref *Ref) Object() root.Object { 57 uid := ref.UID() 58 if uid == 0 { 59 return nil 60 } 61 obj, ok := ref.pid.objs[uid] 62 if !ok { 63 return nil 64 } 65 return obj 66 } 67 68 func (ref *Ref) UnmarshalROOT(r *rbytes.RBuffer) error { 69 if r.Err() != nil { 70 return r.Err() 71 } 72 73 r.ReadObject(&ref.obj) 74 75 switch { 76 case ref.obj.TestBits(kHasUUID): 77 _ = r.ReadString() // UUID string 78 default: 79 _ = r.ReadU16() // pid 80 } 81 82 return nil 83 } 84 85 func (ref *Ref) MarshalROOT(w *rbytes.WBuffer) (int, error) { 86 if w.Err() != nil { 87 return 0, w.Err() 88 } 89 90 beg := w.Pos() 91 w.WriteObject(&ref.obj) 92 93 switch { 94 case ref.obj.TestBits(kHasUUID): 95 panic("rbase: TRef with UUID not supported") 96 default: 97 w.WriteU16(uint16(ref.UID())) // FIXME(sbinet): this should go thru TFile. 98 } 99 100 return int(w.Pos() - beg), w.Err() 101 } 102 103 func init() { 104 f := func() reflect.Value { 105 o := &Ref{} 106 return reflect.ValueOf(o) 107 } 108 rtypes.Factory.Add("TRef", f) 109 } 110 111 var ( 112 _ root.Object = (*Ref)(nil) 113 _ root.Named = (*Ref)(nil) 114 _ rbytes.Marshaler = (*Ref)(nil) 115 _ rbytes.Unmarshaler = (*Ref)(nil) 116 )