github.com/enbility/spine-go@v0.7.0/spine/function_data.go (about)

     1  package spine
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"github.com/enbility/ship-go/logging"
     8  	"github.com/enbility/spine-go/api"
     9  	"github.com/enbility/spine-go/model"
    10  	"github.com/enbility/spine-go/util"
    11  )
    12  
    13  type FunctionData[T any] struct {
    14  	functionType model.FunctionType
    15  	data         *T
    16  
    17  	mux sync.Mutex
    18  }
    19  
    20  func NewFunctionData[T any](function model.FunctionType) *FunctionData[T] {
    21  	return &FunctionData[T]{
    22  		functionType: function,
    23  	}
    24  }
    25  
    26  var _ api.FunctionDataInterface = (*FunctionData[int])(nil)
    27  
    28  /* FunctionDataInterface */
    29  
    30  func (r *FunctionData[T]) FunctionType() model.FunctionType {
    31  	return r.functionType
    32  }
    33  
    34  func (r *FunctionData[T]) SupportsPartialWrite() bool {
    35  	return util.Implements[T, model.Updater]()
    36  }
    37  
    38  func (r *FunctionData[T]) DataCopy() *T {
    39  	r.mux.Lock()
    40  	defer r.mux.Unlock()
    41  
    42  	// copy the data and return it as the data can be updated
    43  	// and newly assigned at any time otherwise we run into panics
    44  	// because of invalid memory address or nil pointer dereference
    45  	var copiedData T
    46  	if r.data == nil {
    47  		return nil
    48  	}
    49  
    50  	copiedData = *r.data
    51  
    52  	return &copiedData
    53  }
    54  
    55  func (r *FunctionData[T]) UpdateData(remoteWrite, persist bool, newData *T, filterPartial *model.FilterType, filterDelete *model.FilterType) (any, *model.ErrorType) {
    56  	r.mux.Lock()
    57  	defer r.mux.Unlock()
    58  
    59  	if filterPartial == nil && filterDelete == nil && persist {
    60  		// just set the data
    61  		r.data = newData
    62  		return r.data, nil
    63  	}
    64  
    65  	if !r.SupportsPartialWrite() {
    66  		return nil, model.NewErrorTypeFromString(fmt.Sprintf("partial updates are not supported for type '%s'", util.Type[T]().Name()))
    67  	}
    68  
    69  	if r.data == nil {
    70  		r.data = new(T)
    71  	}
    72  
    73  	updater := any(r.data).(model.Updater)
    74  	data, success := updater.UpdateList(remoteWrite, persist, newData, filterPartial, filterDelete)
    75  	if !success {
    76  		return nil, model.NewErrorTypeFromString("update failed, likely not allowed to write")
    77  	}
    78  
    79  	return data, nil
    80  }
    81  
    82  func (r *FunctionData[T]) DataCopyAny() any {
    83  	return r.DataCopy()
    84  }
    85  
    86  func (r *FunctionData[T]) UpdateDataAny(remoteWrite, persist bool, newData any, filterPartial *model.FilterType, filterDelete *model.FilterType) (any, *model.ErrorType) {
    87  	data, err := r.UpdateData(remoteWrite, persist, newData.(*T), filterPartial, filterDelete)
    88  	if err != nil {
    89  		logging.Log().Debug(err.String())
    90  	}
    91  
    92  	return data, err
    93  }