diff --git a/concurrent/collections/PublisherMessageQueue_test.go b/concurrent/collections/PublisherMessageQueue_test.go index 8760608..928d588 100644 --- a/concurrent/collections/PublisherMessageQueue_test.go +++ b/concurrent/collections/PublisherMessageQueue_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/tursom/GoCollections/util/unsafe" + "github.com/tursom/GoCollections/unsafe" ) func TestPublisherMessageQueueNode_Sizeof(t *testing.T) { diff --git a/encoding/hex/hex.go b/encoding/hex/hex.go new file mode 100644 index 0000000..35de56c --- /dev/null +++ b/encoding/hex/hex.go @@ -0,0 +1,15 @@ +package hex + +import ( + "encoding/hex" + + "github.com/tursom/GoCollections/unsafe" +) + +func EncodeToString[T any](arr []T) string { + return hex.EncodeToString(unsafe.AsBytes(arr)) +} + +func DecodeString(s string) ([]byte, error) { + return hex.DecodeString(s) +} diff --git a/lang/Array.go b/lang/Array.go new file mode 100644 index 0000000..b934e9b --- /dev/null +++ b/lang/Array.go @@ -0,0 +1,74 @@ +package lang + +type ( + Array[T any] []T + + Int8Array Array[int32] + Int16Array Array[int32] + Int32Array Array[int32] + Int64Array Array[int64] + UInt8Array Array[uint32] + UInt16Array Array[uint32] + UInt32Array Array[uint32] + UInt64Array Array[uint64] +) + +func (a Array[T]) Array() []T { + return a +} + +func (a Int8Array) SetBit(bit int, up bool) (old bool) { + arrIndex := bit / 8 + i := &a[arrIndex] + + return SwapBit(i, bit%8, up) +} + +func (a Int16Array) SetBit(bit int, up bool) (old bool) { + arrIndex := bit / 16 + i := &a[arrIndex] + + return SwapBit(i, bit%16, up) +} + +func (a Int32Array) SetBit(bit int, up bool) (old bool) { + arrIndex := bit / 32 + i := &a[arrIndex] + + return SwapBit(i, bit%32, up) +} + +func (a Int64Array) SetBit(bit int, up bool) (old bool) { + arrIndex := bit / 64 + i := &a[arrIndex] + + return SwapBit(i, bit%64, up) +} + +func (a UInt8Array) SetBit(bit int, up bool) (old bool) { + arrIndex := bit / 8 + i := &a[arrIndex] + + return SwapBit(i, bit%8, up) +} + +func (a UInt16Array) SetBit(bit int, up bool) (old bool) { + arrIndex := bit / 16 + i := &a[arrIndex] + + return SwapBit(i, bit%16, up) +} + +func (a UInt32Array) SetBit(bit int, up bool) (old bool) { + arrIndex := bit / 32 + i := &a[arrIndex] + + return SwapBit(i, bit%32, up) +} + +func (a UInt64Array) SetBit(bit int, up bool) (old bool) { + arrIndex := bit / 64 + i := &a[arrIndex] + + return SwapBit(i, bit%64, up) +} diff --git a/lang/Lang.go b/lang/Lang.go index b2e8dc9..aae9253 100644 --- a/lang/Lang.go +++ b/lang/Lang.go @@ -8,7 +8,6 @@ package lang import ( "reflect" - "unsafe" ) func TypeName[T any]() string { @@ -54,11 +53,3 @@ func Cast[T any](v any) T { return t } } - -func ForceCast[T any](v unsafe.Pointer) *T { - if v == nil { - return nil - } else { - return (*T)(v) - } -} diff --git a/lang/Number.go b/lang/Number.go index e2f62cc..64527e7 100644 --- a/lang/Number.go +++ b/lang/Number.go @@ -12,3 +12,16 @@ type Number interface { ToUInt64() UInt64 ToFloat64() Float64 } + +func SwapBit[T int32 | int64 | uint32 | uint64](p *T, bit int, new bool) (old bool) { + location := T(1) << bit + oldValue := *p + var newValue T + if new { + newValue = oldValue | location + } else { + newValue = oldValue & ^location + } + *p = newValue + return oldValue&newValue != 0 +} diff --git a/lang/atomic/Array.go b/lang/atomic/Array.go index 3ca636b..4d4a3b1 100644 --- a/lang/atomic/Array.go +++ b/lang/atomic/Array.go @@ -6,111 +6,188 @@ package atomic +import "github.com/tursom/GoCollections/lang" + type ( - Array[T any] struct { - atomic Atomic[T] - array []T - } - Int32Array struct { - Array[int32] - } - Int64Array struct { - Array[int64] - } - UInt32Array struct { - Array[uint32] - } - UInt64Array struct { - Array[uint64] - } + Array[T any] lang.Array[*T] + Int32Array lang.Array[Int32] + Int64Array lang.Array[Int64] + UInt32Array lang.Array[UInt32] + UInt64Array lang.Array[UInt64] ) -func NewArray[T any](size int) *Array[*T] { - return &Array[*T]{ - atomic: GetAtomic[T](), - array: make([]*T, size), - } +func NewArray[T any](size int) Array[T] { + return make([]*T, size) } -func CapArray[T any](array []*T) *Array[*T] { - return &Array[*T]{ - atomic: GetAtomic[T](), - array: array, - } +func CapArray[T any](array []*T) Array[T] { + return array } -func NewInt32Array(size int) *Int32Array { - return &Int32Array{ - Array[int32]{ - atomic: Int32F, - array: make([]int32, size), - }, - } +func NewInt32Array(size int) Int32Array { + return make(Int32Array, size) } -func NewInt64Array(size int) *Int64Array { - return &Int64Array{ - Array[int64]{ - atomic: Int64F, - array: make([]int64, size), - }, - } +func NewInt64Array(size int) Int64Array { + return make(Int64Array, size) } -func NewUInt32Array(size int) *UInt32Array { - return &UInt32Array{ - Array[uint32]{ - atomic: UInt32F, - array: make([]uint32, size), - }, - } +func NewUInt32Array(size int) UInt32Array { + return make(UInt32Array, size) } -func NewUInt64Array(size int) *UInt64Array { - return &UInt64Array{ - Array[uint64]{ - atomic: UInt64F, - array: make([]uint64, size), - }, - } +func NewUInt64Array(size int) UInt64Array { + return make(UInt64Array, size) } -func (a *Array[T]) Len() int { - return len(a.array) +func (a Array[T]) Len() int { + return len(a) } -func (a *Array[T]) Array() []T { - return a.array +func (a Array[T]) Array() []*T { + return a } -func (a *Array[T]) Get(index int) T { - return a.atomic.Load()(&a.array[index]) +func (a Array[T]) Get(index int) *T { + return GetAtomizer[T]().Load()(&a[index]) } -func (a *Array[T]) Set(index int, p T) { - a.atomic.Store()(&a.array[index], p) +func (a Int32Array) Get(index int) int32 { + return a[index].Load() } -func (a *Array[T]) Swap(index int, p T) (old T) { - return a.atomic.Swap()(&a.array[index], p) +func (a Int64Array) Get(index int) int64 { + return a[index].Load() } -func (a *Array[T]) CompareAndSwap(index int, old, new T) (swapped bool) { - return a.atomic.CompareAndSwap()(&a.array[index], old, new) +func (a UInt32Array) Get(index int) uint32 { + return a[index].Load() } -func (a *Int32Array) Add(index int, value int32) { - AddInt32(&a.array[index], value) +func (a UInt64Array) Get(index int) uint64 { + return a[index].Load() } -func (a *Int64Array) Add(index int, value int64) { - AddInt64(&a.array[index], value) +func (a Array[T]) Set(index int, p *T) { + GetAtomizer[T]().Store()(&a[index], p) } -func (a *UInt32Array) Add(index int, value uint32) { - AddUInt32(&a.array[index], value) +func (a Int32Array) Set(index int, v int32) { + a[index].Store(v) } -func (a *UInt64Array) Add(index int, value uint64) { - AddUInt64(&a.array[index], value) +func (a Int64Array) Set(index int, v int64) { + a[index].Store(v) +} + +func (a UInt32Array) Set(index int, v uint32) { + a[index].Store(v) +} + +func (a UInt64Array) Set(index int, v uint64) { + a[index].Store(v) +} + +func (a Array[T]) Swap(index int, p *T) (old *T) { + return GetAtomizer[T]().Swap()(&a[index], p) +} + +func (a Int32Array) Swap(index int, new int32) (old int32) { + return a[index].Swap(new) +} + +func (a Int64Array) Swap(index int, new int64) (old int64) { + return a[index].Swap(new) +} + +func (a UInt32Array) Swap(index int, new uint32) (old uint32) { + return a[index].Swap(new) +} + +func (a UInt64Array) Swap(index int, new uint64) (old uint64) { + return a[index].Swap(new) +} + +func (a Array[T]) CompareAndSwap(index int, old, new *T) (swapped bool) { + return GetAtomizer[T]().CompareAndSwap()(&a[index], old, new) +} + +func (a Int32Array) CompareAndSwap(index int, old, new int32) (swapped bool) { + return a[index].CompareAndSwap(old, new) +} + +func (a Int64Array) CompareAndSwap(index int, old, new int64) (swapped bool) { + return a[index].CompareAndSwap(old, new) +} + +func (a UInt32Array) CompareAndSwap(index int, old, new uint32) (swapped bool) { + return a[index].CompareAndSwap(old, new) +} + +func (a UInt64Array) CompareAndSwap(index int, old, new uint64) (swapped bool) { + return a[index].CompareAndSwap(old, new) +} + +func (a Int32Array) Add(index int, value int32) { + a[index].Add(value) +} + +func (a Int64Array) Add(index int, value int64) { + a[index].Add(value) +} + +func (a UInt32Array) Add(index int, value uint32) { + a[index].Add(value) +} + +func (a UInt64Array) Add(index int, value uint64) { + a[index].Add(value) +} + +func (a Int32Array) BitLength() int { + return len(a) * 32 +} + +func (a Int64Array) BitLength() int { + return len(a) * 64 +} + +func (a UInt32Array) BitLength() int { + return len(a) * 32 +} + +func (a UInt64Array) BitLength() int { + return len(a) * 64 +} + +func (a Int32Array) SetBit(bit int, up bool) (old bool) { + return a[bit/32].SetBit(bit%32, up) +} + +func (a Int64Array) SetBit(bit int, up bool) (old bool) { + return a[bit/64].SetBit(bit%64, up) +} + +func (a UInt32Array) SetBit(bit int, up bool) (old bool) { + return a[bit/32].SetBit(bit%32, up) +} + +func (a UInt64Array) SetBit(bit int, up bool) (old bool) { + return a[bit/64].SetBit(bit%64, up) +} + +func (a Int32Array) CompareAndSwapBit(bit int, old, new bool) (swapped bool) { + return a[bit/32].CompareAndSwapBit(bit%32, old, new) +} + +func (a Int64Array) CompareAndSwapBit(bit int, old, new bool) (swapped bool) { + return a[bit/64].CompareAndSwapBit(bit%64, old, new) +} + +func (a UInt32Array) CompareAndSwapBit(bit int, old, new bool) (swapped bool) { + return a[bit/32].CompareAndSwapBit(bit%32, old, new) +} + +func (a UInt64Array) CompareAndSwapBit(bit int, old, new bool) (swapped bool) { + return a[bit/64].CompareAndSwapBit(bit%64, old, new) } diff --git a/lang/atomic/Array_test.go b/lang/atomic/Array_test.go new file mode 100644 index 0000000..c935188 --- /dev/null +++ b/lang/atomic/Array_test.go @@ -0,0 +1,21 @@ +package atomic + +import ( + "fmt" + "reflect" + "testing" + + "github.com/tursom/GoCollections/encoding/hex" + "github.com/tursom/GoCollections/lang" +) + +func TestNewInt32Array_SetBit(t *testing.T) { + fmt.Println(reflect.TypeOf(lang.Nil[atomizerImpl[int]]()).Align()) + + array := NewInt32Array(16) + for i := 0; i < 16; i++ { + array.SetBit(10*i, true) + } + fmt.Println(array) + fmt.Println(hex.EncodeToString(array)) +} diff --git a/lang/atomic/Atomic.go b/lang/atomic/Atomic.go index 5f12323..0c30cac 100644 --- a/lang/atomic/Atomic.go +++ b/lang/atomic/Atomic.go @@ -14,7 +14,7 @@ import ( ) type ( - Atomizer[T any] interface { + Atomic[T any] interface { Swap(new T) (old T) CompareAndSwap(old, new T) (swapped bool) Load() (val T) @@ -26,91 +26,91 @@ type ( CompareAndSwapBit(bit int, old, new bool) (swapped bool) } - Atomic[T any] interface { + Atomizer[T any] interface { Swap() func(addr *T, new T) (old T) CompareAndSwap() func(addr *T, old, new T) (swapped bool) Load() func(addr *T) (val T) Store() func(addr *T, val T) } - atomicImpl[T any] struct { + atomizerImpl[T any] struct { swap func(addr *T, new T) (old T) compareAndSwap func(addr *T, old, new T) (swapped bool) load func(addr *T) (val T) store func(addr *T, val T) } - - atomicTyped[T any] struct { - } ) -//goland:noinspection GoUnusedGlobalVariable var ( - Int32F Atomic[int32] = &atomicImpl[int32]{ + int32Atomizer = &atomizerImpl[int32]{ SwapInt32, CompareAndSwapInt32, LoadInt32, StoreInt32, } - Int64F Atomic[int64] = &atomicImpl[int64]{ + int64Atomizer = &atomizerImpl[int64]{ SwapInt64, CompareAndSwapInt64, LoadInt64, StoreInt64, } - UInt32F Atomic[uint32] = &atomicImpl[uint32]{ + uint32Atomizer = &atomizerImpl[uint32]{ SwapUInt32, CompareAndSwapUInt32, LoadUint32, StoreUInt32, } - UInt64F Atomic[uint64] = &atomicImpl[uint64]{ + uint64Atomizer = &atomizerImpl[uint64]{ SwapUInt64, CompareAndSwapUInt64, LoadUint64, StoreUInt64, } - PointerF Atomic[unsafe.Pointer] = &atomicImpl[unsafe.Pointer]{ - UnsafeSwapPointer, - UnsafeCompareAndSwapPointer, - UnsafeLoadPointer, - UnsafeStorePointer, + pointerAtomizer = &atomizerImpl[unsafe.Pointer]{ + atomic.SwapPointer, + atomic.CompareAndSwapPointer, + atomic.LoadPointer, + atomic.StorePointer, } ) -func GetAtomic[T any]() Atomic[*T] { - return atomicTyped[T]{} +func Int32Atomizer() Atomizer[int32] { + return int32Atomizer } -func (a atomicTyped[T]) Swap() func(addr **T, new *T) (old *T) { - return SwapPointer[T] +func Int64Atomizer() Atomizer[int64] { + return int64Atomizer } -func (a atomicTyped[T]) CompareAndSwap() func(addr **T, old *T, new *T) (swapped bool) { - return CompareAndSwapPointer[T] +func UInt32Atomizer() Atomizer[uint32] { + return uint32Atomizer } -func (a atomicTyped[T]) Load() func(addr **T) (val *T) { - return LoadPointer[T] +func UInt64Atomizer() Atomizer[uint64] { + return uint64Atomizer } -func (a atomicTyped[T]) Store() func(addr **T, val *T) { - return StorePointer[T] +func PointerAtomizer() Atomizer[unsafe.Pointer] { + return pointerAtomizer } -func (a *atomicImpl[T]) Swap() func(addr *T, new T) (old T) { +func GetAtomizer[T any]() Atomizer[*T] { + return (*atomizerImpl[*T])(unsafe.Pointer(pointerAtomizer)) +} + +func (a *atomizerImpl[T]) Swap() func(addr *T, new T) (old T) { return a.swap } -func (a *atomicImpl[T]) CompareAndSwap() func(addr *T, old T, new T) (swapped bool) { +func (a *atomizerImpl[T]) CompareAndSwap() func(addr *T, old T, new T) (swapped bool) { return a.compareAndSwap } -func (a *atomicImpl[T]) Load() func(addr *T) (val T) { +func (a *atomizerImpl[T]) Load() func(addr *T) (val T) { return a.load } -func (a *atomicImpl[T]) Store() func(addr *T, val T) { +func (a *atomizerImpl[T]) Store() func(addr *T, val T) { return a.store } diff --git a/lang/atomic/Atomic_test.go b/lang/atomic/Atomic_test.go new file mode 100644 index 0000000..a91361d --- /dev/null +++ b/lang/atomic/Atomic_test.go @@ -0,0 +1,15 @@ +package atomic + +import ( + "fmt" + "testing" +) + +func TestGetAtomizer(t *testing.T) { + atomizer := GetAtomizer[int32]() + var ref *int32 + var obj int32 = 1 + atomizer.CompareAndSwap()(&ref, nil, &obj) + + fmt.Println(*ref) +} diff --git a/lang/atomic/Bool.go b/lang/atomic/Bool.go index 13ebf8f..733420d 100644 --- a/lang/atomic/Bool.go +++ b/lang/atomic/Bool.go @@ -6,19 +6,17 @@ package atomic -type Bool struct { - i Int32 -} +type Bool Int32 func (v *Bool) Load() (val bool) { - return v.i.Load() != 0 + return (*Int32)(v).Load() != 0 } func (v *Bool) Store(val bool) { if val { - v.i.Store(1) + (*Int32)(v).Store(1) } else { - v.i.Store(0) + (*Int32)(v).Store(0) } } @@ -27,7 +25,7 @@ func (v *Bool) Swap(new bool) (old bool) { if new { n = 1 } - return v.i.Swap(n) != 0 + return (*Int32)(v).Swap(n) != 0 } func (v *Bool) CompareAndSwap(old, new bool) (swapped bool) { @@ -39,5 +37,5 @@ func (v *Bool) CompareAndSwap(old, new bool) (swapped bool) { if new { n = 1 } - return v.i.CompareAndSwap(o, n) + return (*Int32)(v).CompareAndSwap(o, n) } diff --git a/lang/atomic/Float32.go b/lang/atomic/Float32.go index 50a2b6f..9766be6 100644 --- a/lang/atomic/Float32.go +++ b/lang/atomic/Float32.go @@ -42,10 +42,10 @@ func (v *Float32) CompareAndSwap(old, new float32) (swapped bool) { } func (v *Float32) Add(f float32) (new float32) { - old := float32(*v) + old := v.Load() new = old + f for !v.CompareAndSwap(old, new) { - old = float32(*v) + old = v.Load() new = old + f } diff --git a/lang/atomic/Float64.go b/lang/atomic/Float64.go index 3f36bda..276b033 100644 --- a/lang/atomic/Float64.go +++ b/lang/atomic/Float64.go @@ -42,10 +42,10 @@ func (v *Float64) CompareAndSwap(old, new float64) (swapped bool) { } func (v *Float64) Add(f float64) (new float64) { - old := float64(*v) + old := v.Load() new = old + f for !v.CompareAndSwap(old, new) { - old = float64(*v) + old = v.Load() new = old + f } diff --git a/lang/atomic/Int32_test.go b/lang/atomic/Int32_test.go index eae9e0f..7707c20 100644 --- a/lang/atomic/Int32_test.go +++ b/lang/atomic/Int32_test.go @@ -8,12 +8,9 @@ package atomic import ( "fmt" - "reflect" "sync" "testing" "time" - - "github.com/tursom/GoCollections/lang" ) func TestInt32_SetBit(t *testing.T) { @@ -56,14 +53,3 @@ func TestInt32_CompareAndSwapBit(t *testing.T) { time.Sleep(1 * time.Second) fmt.Println(i.Load()) } - -func TestTypeConv(t *testing.T) { - var intV lang.Int32 - var i any = intV - _, ok := i.(lang.AsInt32) - fmt.Println(reflect.TypeOf(i), ok) - - i = &intV - _, ok = i.(lang.AsInt32) - fmt.Println(reflect.TypeOf(i), ok) -} diff --git a/lang/atomic/Reference.go b/lang/atomic/Reference.go index 7934c9b..6a72a22 100644 --- a/lang/atomic/Reference.go +++ b/lang/atomic/Reference.go @@ -11,21 +11,15 @@ import ( "unsafe" "github.com/tursom/GoCollections/lang" -) -//goland:noinspection GoUnusedGlobalVariable -var ( - UnsafeLoadPointer = atomic.LoadPointer - UnsafeStorePointer = atomic.StorePointer - UnsafeSwapPointer = atomic.SwapPointer - UnsafeCompareAndSwapPointer = atomic.CompareAndSwapPointer + unsafe2 "github.com/tursom/GoCollections/unsafe" ) type ( Pointer = unsafe.Pointer PPointer = *unsafe.Pointer - // Reference atomic type T reference + // Reference atomizer type T reference Reference[T any] struct { lang.BaseObject p *T @@ -34,16 +28,16 @@ type ( // NewReference new *Reference[T] init by given reference func NewReference[T any](reference *T) *Reference[T] { - return lang.ForceCast[Reference[T]](Pointer(&reference)) + return unsafe2.ForceCast[Reference[T]](Pointer(&reference)) } // ReferenceOf cast **T to *Reference[T] func ReferenceOf[T any](reference **T) *Reference[T] { - return lang.ForceCast[Reference[T]](Pointer(reference)) + return unsafe2.ForceCast[Reference[T]](Pointer(reference)) } func ReferenceUintptr[T any](reference *uintptr) *Reference[T] { - return lang.ForceCast[Reference[T]](Pointer(reference)) + return unsafe2.ForceCast[Reference[T]](Pointer(reference)) } func (r *Reference[T]) AsPointer() Pointer { @@ -55,7 +49,7 @@ func (r *Reference[T]) AsPPointer() PPointer { } func (r *Reference[T]) AsUintptr() *TypedUintptr[T] { - return lang.ForceCast[TypedUintptr[T]](r.AsPointer()) + return unsafe2.ForceCast[TypedUintptr[T]](r.AsPointer()) } func (r *Reference[T]) pointer() **T { diff --git a/lang/atomic/Uintptr.go b/lang/atomic/Uintptr.go index 360840a..ab2db56 100644 --- a/lang/atomic/Uintptr.go +++ b/lang/atomic/Uintptr.go @@ -9,7 +9,7 @@ package atomic import ( "sync/atomic" - "github.com/tursom/GoCollections/lang" + "github.com/tursom/GoCollections/unsafe" ) type ( @@ -17,8 +17,8 @@ type ( TypedUintptr[T any] Uintptr ) -func (p Uintptr) Raw() uintptr { - return uintptr(p) +func (p *Uintptr) Raw() uintptr { + return uintptr(*p) } func (p *Uintptr) RawP() *uintptr { @@ -48,8 +48,8 @@ func (p *Uintptr) CompareAndSwap(old, new Uintptr) (swapped bool) { return atomic.CompareAndSwapUintptr((*uintptr)(p), uintptr(old), uintptr(new)) } -func (p TypedUintptr[T]) Raw() uintptr { - return uintptr(p) +func (p *TypedUintptr[T]) Raw() uintptr { + return uintptr(*p) } func (p *TypedUintptr[T]) RawP() *uintptr { @@ -65,11 +65,11 @@ func (p *TypedUintptr[T]) AsPPointer() PPointer { } func (tp *TypedUintptr[T]) AsReference() *Reference[T] { - return lang.ForceCast[Reference[T]](Pointer(tp)) + return unsafe.ForceCast[Reference[T]](Pointer(tp)) } -func (tp TypedUintptr[T]) Uintptr() Uintptr { - return Uintptr(tp) +func (tp *TypedUintptr[T]) Uintptr() Uintptr { + return Uintptr(*tp) } func (tp *TypedUintptr[T]) PUintptr() *Uintptr { diff --git a/unsafe/unsafe.go b/unsafe/unsafe.go new file mode 100644 index 0000000..f40f31a --- /dev/null +++ b/unsafe/unsafe.go @@ -0,0 +1,44 @@ +package unsafe + +import ( + "reflect" + "unsafe" + + "github.com/tursom/GoCollections/lang" +) + +type slice struct { + array unsafe.Pointer + len int + cap int +} + +func ForceCast[T any](v unsafe.Pointer) *T { + if v == nil { + return nil + } else { + return (*T)(v) + } +} + +func Sizeof[T any]() uintptr { + return unsafe.Sizeof(lang.Nil[T]()) +} + +// AsBytes cast any slice as []byte with same pinter, real len and real cap +func AsBytes[T any](arr []T) []byte { + sarr := *ForceCast[slice](unsafe.Pointer(&arr)) + typeAlign := reflect.TypeOf(lang.Nil[T]()).Align() + asBytes := unsafe.Pointer(&slice{ + array: sarr.array, + len: sarr.len * typeAlign, + cap: sarr.cap * typeAlign, + }) + + return *ForceCast[[]byte](asBytes) +} + +// AsString cast bytes as string +func AsString(bytes []byte) string { + return *ForceCast[string](unsafe.Pointer(&bytes)) +} diff --git a/util/unsafe/unsafe.go b/util/unsafe/unsafe.go deleted file mode 100644 index df81a6b..0000000 --- a/util/unsafe/unsafe.go +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2022 tursom. All rights reserved. - * Use of this source code is governed by a GPL-3 - * license that can be found in the LICENSE file. - */ - -package unsafe - -import ( - "unsafe" - - "github.com/tursom/GoCollections/lang" -) - -func Sizeof[T any]() uintptr { - return unsafe.Sizeof(lang.Nil[T]()) -}