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

     1  // Copyright 2023 Huan Du. All rights reserved.
     2  // Licensed under the MIT license that can be found in the LICENSE file.
     3  
     4  package clone
     5  
     6  import (
     7  	"reflect"
     8  	"unsafe"
     9  )
    10  
    11  // AllocatorMethods defines all methods required by allocator.
    12  // If any of these methods is nil, allocator will use default method which allocates memory from heap.
    13  type AllocatorMethods struct {
    14  	// Parent is the allocator which handles all unhandled methods.
    15  	// If it's nil, it will be the default allocator.
    16  	Parent *Allocator
    17  
    18  	New       func(pool unsafe.Pointer, t reflect.Type) reflect.Value
    19  	MakeSlice func(pool unsafe.Pointer, t reflect.Type, len, cap int) reflect.Value
    20  	MakeMap   func(pool unsafe.Pointer, t reflect.Type, n int) reflect.Value
    21  	MakeChan  func(pool unsafe.Pointer, t reflect.Type, buffer int) reflect.Value
    22  	IsScalar  func(k reflect.Kind) bool
    23  }
    24  
    25  func (am *AllocatorMethods) parent() *Allocator {
    26  	if am != nil && am.Parent != nil {
    27  		return am.Parent
    28  	}
    29  
    30  	return nil
    31  }
    32  
    33  func (am *AllocatorMethods) new(parent *Allocator, pool unsafe.Pointer) func(pool unsafe.Pointer, t reflect.Type) reflect.Value {
    34  	if am != nil && am.New != nil {
    35  		return am.New
    36  	}
    37  
    38  	if parent != nil {
    39  		if parent.pool == pool {
    40  			return parent.new
    41  		} else {
    42  			return func(pool unsafe.Pointer, t reflect.Type) reflect.Value {
    43  				return parent.New(t)
    44  			}
    45  		}
    46  	}
    47  
    48  	return defaultAllocator.new
    49  }
    50  
    51  func (am *AllocatorMethods) makeSlice(parent *Allocator, pool unsafe.Pointer) func(pool unsafe.Pointer, t reflect.Type, len, cap int) reflect.Value {
    52  	if am != nil && am.MakeSlice != nil {
    53  		return am.MakeSlice
    54  	}
    55  
    56  	if parent != nil {
    57  		if parent.pool == pool {
    58  			return parent.makeSlice
    59  		} else {
    60  			return func(pool unsafe.Pointer, t reflect.Type, len, cap int) reflect.Value {
    61  				return parent.MakeSlice(t, len, cap)
    62  			}
    63  		}
    64  	}
    65  
    66  	return defaultAllocator.makeSlice
    67  }
    68  
    69  func (am *AllocatorMethods) makeMap(parent *Allocator, pool unsafe.Pointer) func(pool unsafe.Pointer, t reflect.Type, n int) reflect.Value {
    70  	if am != nil && am.MakeMap != nil {
    71  		return am.MakeMap
    72  	}
    73  
    74  	if parent != nil {
    75  		if parent.pool == pool {
    76  			return parent.makeMap
    77  		} else {
    78  			return func(pool unsafe.Pointer, t reflect.Type, n int) reflect.Value {
    79  				return parent.MakeMap(t, n)
    80  			}
    81  		}
    82  	}
    83  
    84  	return defaultAllocator.makeMap
    85  }
    86  
    87  func (am *AllocatorMethods) makeChan(parent *Allocator, pool unsafe.Pointer) func(pool unsafe.Pointer, t reflect.Type, buffer int) reflect.Value {
    88  	if am != nil && am.MakeChan != nil {
    89  		return am.MakeChan
    90  	}
    91  
    92  	if parent != nil {
    93  		if parent.pool == pool {
    94  			return parent.makeChan
    95  		} else {
    96  			return func(pool unsafe.Pointer, t reflect.Type, buffer int) reflect.Value {
    97  				return parent.MakeChan(t, buffer)
    98  			}
    99  		}
   100  	}
   101  
   102  	return defaultAllocator.makeChan
   103  }
   104  
   105  func (am *AllocatorMethods) isScalar(parent *Allocator) func(t reflect.Kind) bool {
   106  	if am != nil && am.IsScalar != nil {
   107  		return am.IsScalar
   108  	}
   109  
   110  	if parent != nil {
   111  		return parent.isScalar
   112  	}
   113  
   114  	return defaultAllocator.isScalar
   115  }