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  )