github.com/modern-go/reflect2@v1.0.2/unsafe_slice.go (about) 1 package reflect2 2 3 import ( 4 "reflect" 5 "unsafe" 6 ) 7 8 // sliceHeader is a safe version of SliceHeader used within this package. 9 type sliceHeader struct { 10 Data unsafe.Pointer 11 Len int 12 Cap int 13 } 14 15 type UnsafeSliceType struct { 16 unsafeType 17 elemRType unsafe.Pointer 18 pElemRType unsafe.Pointer 19 elemSize uintptr 20 } 21 22 func newUnsafeSliceType(cfg *frozenConfig, type1 reflect.Type) SliceType { 23 elemType := type1.Elem() 24 return &UnsafeSliceType{ 25 unsafeType: *newUnsafeType(cfg, type1), 26 pElemRType: unpackEFace(reflect.PtrTo(elemType)).data, 27 elemRType: unpackEFace(elemType).data, 28 elemSize: elemType.Size(), 29 } 30 } 31 32 func (type2 *UnsafeSliceType) Set(obj interface{}, val interface{}) { 33 objEFace := unpackEFace(obj) 34 assertType("Type.Set argument 1", type2.ptrRType, objEFace.rtype) 35 valEFace := unpackEFace(val) 36 assertType("Type.Set argument 2", type2.ptrRType, valEFace.rtype) 37 type2.UnsafeSet(objEFace.data, valEFace.data) 38 } 39 40 func (type2 *UnsafeSliceType) UnsafeSet(ptr unsafe.Pointer, val unsafe.Pointer) { 41 *(*sliceHeader)(ptr) = *(*sliceHeader)(val) 42 } 43 44 func (type2 *UnsafeSliceType) IsNil(obj interface{}) bool { 45 if obj == nil { 46 return true 47 } 48 objEFace := unpackEFace(obj) 49 assertType("Type.IsNil argument 1", type2.ptrRType, objEFace.rtype) 50 return type2.UnsafeIsNil(objEFace.data) 51 } 52 53 func (type2 *UnsafeSliceType) UnsafeIsNil(ptr unsafe.Pointer) bool { 54 if ptr == nil { 55 return true 56 } 57 return (*sliceHeader)(ptr).Data == nil 58 } 59 60 func (type2 *UnsafeSliceType) SetNil(obj interface{}) { 61 objEFace := unpackEFace(obj) 62 assertType("SliceType.SetNil argument 1", type2.ptrRType, objEFace.rtype) 63 type2.UnsafeSetNil(objEFace.data) 64 } 65 66 func (type2 *UnsafeSliceType) UnsafeSetNil(ptr unsafe.Pointer) { 67 header := (*sliceHeader)(ptr) 68 header.Len = 0 69 header.Cap = 0 70 header.Data = nil 71 } 72 73 func (type2 *UnsafeSliceType) MakeSlice(length int, cap int) interface{} { 74 return packEFace(type2.ptrRType, type2.UnsafeMakeSlice(length, cap)) 75 } 76 77 func (type2 *UnsafeSliceType) UnsafeMakeSlice(length int, cap int) unsafe.Pointer { 78 header := &sliceHeader{unsafe_NewArray(type2.elemRType, cap), length, cap} 79 return unsafe.Pointer(header) 80 } 81 82 func (type2 *UnsafeSliceType) LengthOf(obj interface{}) int { 83 objEFace := unpackEFace(obj) 84 assertType("SliceType.Len argument 1", type2.ptrRType, objEFace.rtype) 85 return type2.UnsafeLengthOf(objEFace.data) 86 } 87 88 func (type2 *UnsafeSliceType) UnsafeLengthOf(obj unsafe.Pointer) int { 89 header := (*sliceHeader)(obj) 90 return header.Len 91 } 92 93 func (type2 *UnsafeSliceType) SetIndex(obj interface{}, index int, elem interface{}) { 94 objEFace := unpackEFace(obj) 95 assertType("SliceType.SetIndex argument 1", type2.ptrRType, objEFace.rtype) 96 elemEFace := unpackEFace(elem) 97 assertType("SliceType.SetIndex argument 3", type2.pElemRType, elemEFace.rtype) 98 type2.UnsafeSetIndex(objEFace.data, index, elemEFace.data) 99 } 100 101 func (type2 *UnsafeSliceType) UnsafeSetIndex(obj unsafe.Pointer, index int, elem unsafe.Pointer) { 102 header := (*sliceHeader)(obj) 103 elemPtr := arrayAt(header.Data, index, type2.elemSize, "i < s.Len") 104 typedmemmove(type2.elemRType, elemPtr, elem) 105 } 106 107 func (type2 *UnsafeSliceType) GetIndex(obj interface{}, index int) interface{} { 108 objEFace := unpackEFace(obj) 109 assertType("SliceType.GetIndex argument 1", type2.ptrRType, objEFace.rtype) 110 elemPtr := type2.UnsafeGetIndex(objEFace.data, index) 111 return packEFace(type2.pElemRType, elemPtr) 112 } 113 114 func (type2 *UnsafeSliceType) UnsafeGetIndex(obj unsafe.Pointer, index int) unsafe.Pointer { 115 header := (*sliceHeader)(obj) 116 return arrayAt(header.Data, index, type2.elemSize, "i < s.Len") 117 } 118 119 func (type2 *UnsafeSliceType) Append(obj interface{}, elem interface{}) { 120 objEFace := unpackEFace(obj) 121 assertType("SliceType.Append argument 1", type2.ptrRType, objEFace.rtype) 122 elemEFace := unpackEFace(elem) 123 assertType("SliceType.Append argument 2", type2.pElemRType, elemEFace.rtype) 124 type2.UnsafeAppend(objEFace.data, elemEFace.data) 125 } 126 127 func (type2 *UnsafeSliceType) UnsafeAppend(obj unsafe.Pointer, elem unsafe.Pointer) { 128 header := (*sliceHeader)(obj) 129 oldLen := header.Len 130 type2.UnsafeGrow(obj, oldLen+1) 131 type2.UnsafeSetIndex(obj, oldLen, elem) 132 } 133 134 func (type2 *UnsafeSliceType) Cap(obj interface{}) int { 135 objEFace := unpackEFace(obj) 136 assertType("SliceType.Cap argument 1", type2.ptrRType, objEFace.rtype) 137 return type2.UnsafeCap(objEFace.data) 138 } 139 140 func (type2 *UnsafeSliceType) UnsafeCap(ptr unsafe.Pointer) int { 141 return (*sliceHeader)(ptr).Cap 142 } 143 144 func (type2 *UnsafeSliceType) Grow(obj interface{}, newLength int) { 145 objEFace := unpackEFace(obj) 146 assertType("SliceType.Grow argument 1", type2.ptrRType, objEFace.rtype) 147 type2.UnsafeGrow(objEFace.data, newLength) 148 } 149 150 func (type2 *UnsafeSliceType) UnsafeGrow(obj unsafe.Pointer, newLength int) { 151 header := (*sliceHeader)(obj) 152 if newLength <= header.Cap { 153 header.Len = newLength 154 return 155 } 156 newCap := calcNewCap(header.Cap, newLength) 157 newHeader := (*sliceHeader)(type2.UnsafeMakeSlice(header.Len, newCap)) 158 typedslicecopy(type2.elemRType, *newHeader, *header) 159 header.Data = newHeader.Data 160 header.Cap = newHeader.Cap 161 header.Len = newLength 162 } 163 164 func calcNewCap(cap int, expectedCap int) int { 165 if cap == 0 { 166 cap = expectedCap 167 } else { 168 for cap < expectedCap { 169 if cap < 1024 { 170 cap += cap 171 } else { 172 cap += cap / 4 173 } 174 } 175 } 176 return cap 177 }