github.com/wfusion/gofusion@v1.1.14/common/utils/clone/api_go118.go (about)

     1  //go:build go1.18
     2  // +build go1.18
     3  
     4  package clone
     5  
     6  import (
     7  	"reflect"
     8  	"unsafe"
     9  )
    10  
    11  // Clone recursively deep clone v to a new value in heap.
    12  // It assumes that there is no pointer cycle in v,
    13  // e.g. v has a pointer points to v itself.
    14  // If there is a pointer cycle, use Slowly instead.
    15  //
    16  // Clone allocates memory and deeply copies values inside v in depth-first sequence.
    17  // There are a few special rules for following types.
    18  //
    19  //   - Scalar types: all number-like types are copied by value.
    20  //   - func: Copied by value as func is an opaque pointer at runtime.
    21  //   - string: Copied by value as string is immutable by design.
    22  //   - unsafe.Pointer: Copied by value as we don't know what's in it.
    23  //   - chan: A new empty chan is created as we cannot read data inside the old chan.
    24  //
    25  // Unlike many other packages, Clone is able to clone unexported fields of any struct.
    26  // Use this feature wisely.
    27  func Clone[T any](t T) T {
    28  	return cloner.Clone(t).(T)
    29  }
    30  
    31  // Slowly recursively deep clone v to a new value in heap.
    32  // It marks all cloned values internally, thus it can clone v with cycle pointer.
    33  //
    34  // Slowly works exactly the same as Clone. See Clone doc for more details.
    35  func Slowly[T any](t T) T {
    36  	return cloner.CloneSlowly(t).(T)
    37  }
    38  
    39  // Wrap creates a wrapper of v, which must be a pointer.
    40  // If v is not a pointer, Wrap simply returns v and do nothing.
    41  //
    42  // The wrapper is a deep clone of v's value. It holds a shadow copy to v internally.
    43  //
    44  //	t := &T{Foo: 123}
    45  //	v := Wrap(t).(*T)               // v is a clone of t.
    46  //	reflect.DeepEqual(t, v) == true // v equals t.
    47  //	v.Foo = 456                     // v.Foo is changed, but t.Foo doesn't change.
    48  //	orig := Unwrap(v)               // Use `Unwrap` to discard wrapper and return original value, which is t.
    49  //	orig.(*T) == t                  // orig and t is exactly the same.
    50  //	Undo(v)                         // Use `Undo` to discard any change on v.
    51  //	v.Foo == t.Foo                  // Now, the value of v and t are the same again.
    52  func Wrap[T any](t T) T {
    53  	return wrap(t).(T)
    54  }
    55  
    56  // Unwrap returns v's original value if v is a wrapped value.
    57  // Otherwise, simply returns v itself.
    58  func Unwrap[T any](t T) T {
    59  	return unwrap(t).(T)
    60  }
    61  
    62  // Undo discards any change made in wrapped value.
    63  // If v is not a wrapped value, nothing happens.
    64  func Undo[T any](t T) {
    65  	undo(t)
    66  }
    67  
    68  // MarkAsOpaquePointer marks t as an opaque pointer in heap allocator,
    69  // so that all clone methods will copy t by value.
    70  // If t is not a pointer, MarkAsOpaquePointer ignores t.
    71  //
    72  // Here is a list of types marked as opaque pointers by default:
    73  //   - `elliptic.Curve`, which is `*elliptic.CurveParam` or `elliptic.p256Curve`;
    74  //   - `reflect.Type`, which is `*reflect.rtype` defined in `runtime`.
    75  func MarkAsOpaquePointer(t reflect.Type) {
    76  	markAsOpaquePointer(t)
    77  }
    78  
    79  // MarkAsScalar marks t as a scalar type in heap allocator,
    80  // so that all clone methods will copy t by value.
    81  // If t is not struct or pointer to struct, MarkAsScalar ignores t.
    82  //
    83  // In the most cases, it's not necessary to call it explicitly.
    84  // If a struct type contains scalar type fields only, the struct will be marked as scalar automatically.
    85  //
    86  // Here is a list of types marked as scalar by default:
    87  //   - time.Time
    88  //   - reflect.Value
    89  func MarkAsScalar(t reflect.Type) {
    90  	markAsScalar(t)
    91  }
    92  
    93  // SetCustomFunc sets a custom clone function for type t in heap allocator.
    94  // If t is not struct or pointer to struct, SetCustomFunc ignores t.
    95  //
    96  // If fn is nil, remove the custom clone function for type t.
    97  func SetCustomFunc(t reflect.Type, fn Func) {
    98  	setCustomFunc(t, fn)
    99  }
   100  
   101  // FromHeap creates an allocator which allocate memory from heap.
   102  func FromHeap() *Allocator {
   103  	return fromHeap()
   104  }
   105  
   106  // NewAllocator creates an allocator which allocate memory from the pool.
   107  // Both pool and methods are optional.
   108  //
   109  // If methods.New is not nil, the allocator itself is created by calling methods.New.
   110  //
   111  // The pool is a pointer to the memory pool which is opaque to the allocator.
   112  // It's methods' responsibility to allocate memory from the pool properly.
   113  func NewAllocator(pool unsafe.Pointer, methods *AllocatorMethods) (allocator *Allocator) {
   114  	return newAllocator(pool, methods)
   115  }