github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/cache/optional.go (about)

     1  package cache
     2  
     3  import "io"
     4  
     5  // Optional is used to read/write values that can be missing. Most of the case, it will be pointers
     6  // to articulated objects. Optional.MarshalCache first write a boolean indicating if the value
     7  // is present or not. If it is not present, nothing is written next. However, if it is present
     8  // the value will be written using the standard path through WriteValue.
     9  //
    10  // When reading a missing value, we get a correct pointer zero value of nil instead of a pointer to
    11  // initialized zero value from new(Type). new(Type) != nil.
    12  type Optional[T any] struct {
    13  	Value *T
    14  	ptr   *T
    15  }
    16  
    17  func (o *Optional[T]) MarshalCache(writer io.Writer) (err error) {
    18  	present := o.Value != nil
    19  	if err = write(writer, present); err != nil {
    20  		return
    21  	}
    22  	if !present {
    23  		return nil
    24  	}
    25  
    26  	return WriteValue(writer, o.Value)
    27  }
    28  
    29  func (o *Optional[T]) UnmarshalCache(version uint64, reader io.Reader) (err error) {
    30  	var present bool
    31  	if err = read(reader, &present); err != nil {
    32  		return
    33  	}
    34  	if !present {
    35  		return
    36  	}
    37  
    38  	var value T
    39  	if err = ReadValue(reader, &value, version); err != nil {
    40  		return err
    41  	}
    42  	o.ptr = &value
    43  	return
    44  }
    45  
    46  // Get returns pointer to the value that was unmarshaled. We cannot simply set o.Value to point to
    47  // the value read, because nil pointers cannot be dereferenced.
    48  func (o *Optional[T]) Get() *T {
    49  	return o.ptr
    50  }