Skip to content

Commit

Permalink
✨ feat(byte): add new util func: Random(), AppendAny() and with some …
Browse files Browse the repository at this point in the history
…unit tests
  • Loading branch information
inhere committed Apr 19, 2023
1 parent 16f391d commit e86313b
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 1 deletion.
67 changes: 66 additions & 1 deletion byteutil/byteutil.go
Expand Up @@ -2,9 +2,23 @@ package byteutil

import (
"bytes"
"fmt"
"math/rand"
"strconv"
"time"
"unsafe"
)

// Random bytes generate
func Random(length int) ([]byte, error) {
b := make([]byte, length)
// Note that err == nil only if we read len(b) bytes.
if _, err := rand.Read(b); err != nil {
return nil, err
}
return b, nil
}

// FirstLine from command output
func FirstLine(bs []byte) []byte {
if i := bytes.IndexByte(bs, '\n'); i >= 0 {
Expand All @@ -29,7 +43,7 @@ func SafeString(bs []byte, err error) string {
return string(bs)
}

// String convert bytes to string
// String unsafe convert bytes to string
func String(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
Expand All @@ -38,3 +52,54 @@ func String(b []byte) string {
func ToString(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}

// AppendAny append any value to byte slice
func AppendAny(dst []byte, v any) []byte {
if v == nil {
return append(dst, "<nil>"...)
}

switch val := v.(type) {
case []byte:
dst = append(dst, val...)
case string:
dst = append(dst, val...)
case int:
dst = strconv.AppendInt(dst, int64(val), 10)
case int8:
dst = strconv.AppendInt(dst, int64(val), 10)
case int16:
dst = strconv.AppendInt(dst, int64(val), 10)
case int32:
dst = strconv.AppendInt(dst, int64(val), 10)
case int64:
dst = strconv.AppendInt(dst, val, 10)
case uint:
dst = strconv.AppendUint(dst, uint64(val), 10)
case uint8:
dst = strconv.AppendUint(dst, uint64(val), 10)
case uint16:
dst = strconv.AppendUint(dst, uint64(val), 10)
case uint32:
dst = strconv.AppendUint(dst, uint64(val), 10)
case uint64:
dst = strconv.AppendUint(dst, val, 10)
case float32:
dst = strconv.AppendFloat(dst, float64(val), 'f', -1, 32)
case float64:
dst = strconv.AppendFloat(dst, val, 'f', -1, 64)
case bool:
dst = strconv.AppendBool(dst, val)
case time.Time:
dst = val.AppendFormat(dst, time.RFC3339)
case time.Duration:
dst = strconv.AppendInt(dst, int64(val), 10)
case error:
dst = append(dst, val.Error()...)
case fmt.Stringer:
dst = append(dst, val.String()...)
default:
dst = append(dst, fmt.Sprint(v)...)
}
return dst
}
9 changes: 9 additions & 0 deletions byteutil/byteutil_test.go
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/gookit/goutil/byteutil"
"github.com/gookit/goutil/testutil/assert"
"github.com/gookit/goutil/timex"
)

func TestFirstLine(t *testing.T) {
Expand All @@ -32,3 +33,11 @@ func TestMd5(t *testing.T) {
assert.NotEmpty(t, byteutil.Md5("abc"))
assert.NotEmpty(t, byteutil.Md5([]int{12, 34}))
}

func TestAppendAny(t *testing.T) {
assert.Eq(t, []byte("123"), byteutil.AppendAny(nil, 123))
assert.Eq(t, []byte("123"), byteutil.AppendAny([]byte{}, 123))
assert.Eq(t, []byte("123"), byteutil.AppendAny([]byte("1"), 23))
assert.Eq(t, []byte("1<nil>"), byteutil.AppendAny([]byte("1"), nil))
assert.Eq(t, "3600000000000", string(byteutil.AppendAny([]byte{}, timex.OneHour)))
}
26 changes: 26 additions & 0 deletions fmtutil/format_test.go
Expand Up @@ -4,8 +4,10 @@ import (
"fmt"
"testing"

"github.com/gookit/goutil/errorx"
"github.com/gookit/goutil/fmtutil"
"github.com/gookit/goutil/testutil/assert"
"github.com/gookit/goutil/timex"
)

func TestDataSize(t *testing.T) {
Expand Down Expand Up @@ -65,6 +67,30 @@ func TestArgsWithSpaces(t *testing.T) {
assert.Eq(t, "", fmtutil.ArgsWithSpaces([]any{}))
assert.Eq(t, "abc", fmtutil.ArgsWithSpaces([]any{"abc"}))
assert.Eq(t, "23 abc", fmtutil.ArgsWithSpaces([]any{23, "abc"}))

tests := []struct {
args []any
want string
}{
{nil, ""},
{[]any{"a", "b", "c"}, "a b c"},
{[]any{"a", "b", "c", 1, 2, 3}, "a b c 1 2 3"},
{[]any{"a", 1, nil}, "a 1 <nil>"},
{[]any{12, int8(12), int16(12), int32(12), int64(12)}, "12 12 12 12 12"},
{[]any{uint(12), uint8(12), uint16(12), uint32(12), uint64(12)}, "12 12 12 12 12"},
{[]any{float32(12.12), 12.12}, "12.12 12.12"},
{[]any{true, false}, "true false"},
{[]any{[]byte("abc"), []byte("123")}, "abc 123"},
{[]any{timex.OneHour}, "3600000000000"},
{[]any{errorx.Raw("a error message")}, "a error message"},
{[]any{[]int{1, 2, 3}}, "[1 2 3]"},
}

for _, tt := range tests {
assert.Eq(t, tt.want, fmtutil.ArgsWithSpaces(tt.args))
}

assert.NotEmpty(t, fmtutil.ArgsWithSpaces([]any{timex.Now().T()}))
}

func TestStringsToInts(t *testing.T) {
Expand Down

0 comments on commit e86313b

Please sign in to comment.