diff --git a/utils/unsafe.go b/utils/unsafe.go index 9bbd3a5df..de08d8644 100644 --- a/utils/unsafe.go +++ b/utils/unsafe.go @@ -22,15 +22,18 @@ import ( ) // BytesToString casts slice to string without copy -func BytesToString(b []byte) (s string) { +func BytesToString(b []byte) string { if len(b) == 0 { return "" } - bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - sh := reflect.StringHeader{Data: bh.Data, Len: bh.Len} - - return *(*string)(unsafe.Pointer(&sh)) + p := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&b)).Data) + var s string + sh := (*reflect.SliceHeader)(unsafe.Pointer(&s)) + sh.Data = uintptr(p) + sh.Cap = len(b) + sh.Len = len(b) + return s } // StringToBytes casts string to slice without copy @@ -39,8 +42,11 @@ func StringToBytes(s string) []byte { return []byte{} } - sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) - bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} - - return *(*[]byte)(unsafe.Pointer(&bh)) + p := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data) + var b []byte + sh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + sh.Data = uintptr(p) + sh.Cap = len(s) + sh.Len = len(s) + return b } diff --git a/utils/unsafe_test.go b/utils/unsafe_test.go new file mode 100644 index 000000000..75477cef9 --- /dev/null +++ b/utils/unsafe_test.go @@ -0,0 +1,61 @@ +/* +Copyright 2021 RadonDB. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package utils + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBytesToString(t *testing.T) { + { + bs := []byte{0x61, 0x62} + want := "ab" + got := BytesToString(bs) + assert.Equal(t, want, got) + } + + { + bs := []byte{} + want := "" + got := BytesToString(bs) + assert.Equal(t, want, got) + } +} + +func TestSting(t *testing.T) { + { + want := []byte{0x61, 0x62} + got := StringToBytes("ab") + assert.Equal(t, want, got) + } + + { + want := []byte{} + got := StringToBytes("") + assert.Equal(t, want, got) + } +} + +func TestStingToBytes(t *testing.T) { + { + want := []byte{0x53, 0x45, 0x4c, 0x45, 0x43, 0x54, 0x20, 0x2a, 0x20, 0x46, 0x52, 0x4f, 0x4d, 0x20, 0x74, 0x32} + got := StringToBytes("SELECT * FROM t2") + assert.Equal(t, want, got) + } +}