diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 659c0d8..f5ad1be 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -16,8 +16,7 @@ jobs: strategy: matrix: go-version: - - 1.19.x # a minimum supported version(from go.mod) - - 1.20.x + - 1.20.x # a minimum supported version(from go.mod) - 1.21.x - 1.22.x os: [ ubuntu-latest ] diff --git a/go.mod b/go.mod index 7f538e1..4f3f6e9 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/mailgun/holster/v4 -go 1.19 +go 1.20 require ( github.com/Shopify/toxiproxy v2.1.4+incompatible diff --git a/unsafe/unsafe.go b/unsafe/unsafe.go new file mode 100644 index 0000000..82eb14b --- /dev/null +++ b/unsafe/unsafe.go @@ -0,0 +1,20 @@ +package unsafe + +import ( + "unsafe" +) + +// BytesToString converts a byte slice to a string without allocation. The +// returned string reuses the slice byte array. Since Go strings are immutable, +// the bytes passed to BytesToString must not be modified afterwards. +func BytesToString(b []byte) string { + return unsafe.String(unsafe.SliceData(b), len(b)) +} + +// StringToBytes converts a string to a byte slice without allocation. The +// returned byte slice reuses the underlying string byte array. Since Go +// strings are immutable, the bytes returned by StringToBytes must not be +// modified. +func StringToBytes(s string) []byte { + return unsafe.Slice(unsafe.StringData(s), len(s)) +} diff --git a/unsafe/unsafe_test.go b/unsafe/unsafe_test.go new file mode 100644 index 0000000..7497e1e --- /dev/null +++ b/unsafe/unsafe_test.go @@ -0,0 +1,15 @@ +package unsafe + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBytesToString(t *testing.T) { + assert.Equal(t, "hello", BytesToString([]byte("hello"))) +} + +func TestStringToBytes(t *testing.T) { + assert.Equal(t, []byte("hello"), StringToBytes("hello")) +}