Add function to convert to byte array

This commit is contained in:
Marcos Felipe 2023-04-11 00:02:08 +01:00
parent ba0a5b63c8
commit acb6966dc1
No known key found for this signature in database
3 changed files with 187 additions and 1 deletions

11
cast.go
View File

@ -6,7 +6,10 @@
// Package cast provides easy and safe casting in Go.
package cast
import "time"
import (
"encoding/binary"
"time"
)
// ToBool casts an interface to a bool type.
func ToBool(i interface{}) bool {
@ -169,6 +172,12 @@ func ToIntSlice(i interface{}) []int {
return v
}
// ToBytes casts an interface to a []byte type.
func ToBytes(i interface{}, b binary.ByteOrder) []byte {
v, _ := ToBytesE(i, b)
return v
}
// ToDurationSlice casts an interface to a []time.Duration type.
func ToDurationSlice(i interface{}) []time.Duration {
v, _ := ToDurationSliceE(i)

View File

@ -6,10 +6,12 @@
package cast
import (
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"html/template"
"math"
"path"
"reflect"
"testing"
@ -289,6 +291,93 @@ func TestToStringE(t *testing.T) {
}
}
func TestToBytesE(t *testing.T) {
c := qt.New(t)
//Overkill?
expected8 := []byte{math.MaxInt8}
expectedLittle16 := append([]byte{math.MaxUint8}, math.MaxInt8)
expectedBig16 := append(expected8, math.MaxUint8)
expectedLittle32 := append([]byte{math.MaxUint8, math.MaxUint8}, expectedLittle16...)
expectedBig32 := append(expectedBig16, math.MaxUint8, math.MaxUint8)
expectedLittle64 := append([]byte{math.MaxUint8, math.MaxUint8, math.MaxUint8, math.MaxUint8}, expectedLittle32...)
expectedBig64 := append(expectedBig32, math.MaxUint8, math.MaxUint8, math.MaxUint8, math.MaxUint8)
expectedU8 := []byte{math.MaxUint8}
expectedLittleU16 := append(expectedU8, expectedU8...)
expectedLittleU32 := append(expectedLittleU16, expectedLittleU16...)
expectedLittleU64 := append(expectedLittleU32, expectedLittleU32...)
expectedBigU16 := append(expected8, expectedU8...)
expectedBigU32 := append(expectedBigU16, expectedLittleU16...)
expectedBigU64 := append(expectedBigU32, expectedLittleU32...)
tests := []struct {
input interface{}
byteOrder binary.ByteOrder
expect []byte
iserr bool
}{
//LittleEndian
{byte(math.MaxUint8), binary.LittleEndian, expectedU8, false},
{math.MaxInt32, binary.LittleEndian, expectedLittle32, false},
{math.MaxInt64, binary.LittleEndian, expectedLittle64, false},
{uint(math.MaxUint32), binary.LittleEndian, expectedLittleU32, false},
{uint(math.MaxUint64), binary.LittleEndian, expectedLittleU64, false},
{int8(math.MaxInt8), binary.LittleEndian, expected8, false},
{int16(math.MaxInt16), binary.LittleEndian, expectedLittle16, false},
{int32(math.MaxInt32), binary.LittleEndian, expectedLittle32, false},
{int64(math.MaxInt64), binary.LittleEndian, expectedLittle64, false},
{uint8(math.MaxUint8), binary.LittleEndian, expectedU8, false},
{uint16(math.MaxUint16), binary.LittleEndian, expectedLittleU16, false},
{uint32(math.MaxUint32), binary.LittleEndian, expectedLittleU32, false},
{uint64(math.MaxUint64), binary.LittleEndian, expectedLittleU64, false},
{[]byte("one time"), binary.LittleEndian, []byte("one time"), false},
{"one more time", binary.LittleEndian, []byte("one more time"), false},
//BigEndian
{byte(math.MaxUint8), binary.BigEndian, expectedU8, false},
{math.MaxInt32, binary.BigEndian, expectedBig32, false},
{math.MaxInt64, binary.BigEndian, expectedBig64, false},
{uint(math.MaxInt32), binary.BigEndian, expectedBigU32, false},
{uint(math.MaxInt64), binary.BigEndian, expectedBigU64, false},
{int8(math.MaxInt8), binary.BigEndian, expected8, false},
{int16(math.MaxInt16), binary.BigEndian, expectedBig16, false},
{int32(math.MaxInt32), binary.BigEndian, expectedBig32, false},
{int64(math.MaxInt64), binary.BigEndian, expectedBig64, false},
{uint8(math.MaxUint8), binary.BigEndian, expectedU8, false},
{uint16(math.MaxInt16), binary.BigEndian, expectedBigU16, false},
{uint32(math.MaxInt32), binary.BigEndian, expectedBigU32, false},
{uint64(math.MaxInt64), binary.BigEndian, expectedBigU64, false},
{[]byte("one time"), binary.BigEndian, []byte("one time"), false},
{"one more time", binary.BigEndian, []byte("one more time"), false},
// errors
{testing.T{}, binary.LittleEndian, []byte{}, true},
{int8(-8), binary.LittleEndian, []byte{}, true},
{int16(-136), binary.LittleEndian, []byte{}, true},
{int32(-2184), binary.LittleEndian, []byte{}, true},
{int64(-34952), binary.LittleEndian, []byte{}, true},
{true, binary.LittleEndian, []byte{}, true},
{false, binary.LittleEndian, []byte{}, true},
{nil, binary.LittleEndian, []byte{}, true},
}
for i, test := range tests {
errmsg := qt.Commentf("i = %d", i) // assert helper message
v, err := ToBytesE(test.input, test.byteOrder)
if test.iserr {
c.Assert(err, qt.IsNotNil, errmsg)
continue
}
c.Assert(err, qt.IsNil, errmsg)
c.Assert(v, qt.DeepEquals, test.expect, errmsg)
// Non-E test
v = ToBytes(test.input, test.byteOrder)
c.Assert(v, qt.DeepEquals, test.expect, errmsg)
}
}
type foo struct {
val string
}

View File

@ -6,10 +6,12 @@
package cast
import (
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"html/template"
"math"
"reflect"
"strconv"
"strings"
@ -1340,6 +1342,92 @@ func ToIntSliceE(i interface{}) ([]int, error) {
}
}
func ToBytesE(i interface{}, b binary.ByteOrder) ([]byte, error) {
i = indirect(i)
if i == nil {
return []byte{}, fmt.Errorf("unable to cast %#v of type %T to []byte", i, i)
}
switch v := i.(type) {
case []byte:
return v, nil
case byte:
return []byte{v}, nil
case int8:
if v < 0 {
return []byte{}, errNegativeNotAllowed
}
return []byte{byte(v)}, nil
case int16:
if v < 0 {
return []byte{}, errNegativeNotAllowed
}
a := make([]byte, 2)
b.PutUint16(a, uint16(v))
return a, nil
case int32:
if v < 0 {
return []byte{}, errNegativeNotAllowed
}
a := make([]byte, 4)
b.PutUint32(a, uint32(v))
return a, nil
case int64:
if v < 0 {
return []byte{}, errNegativeNotAllowed
}
a := make([]byte, 8)
b.PutUint64(a, uint64(v))
return a, nil
case uint16:
a := make([]byte, 2)
b.PutUint16(a, v)
return a, nil
case uint32:
a := make([]byte, 4)
b.PutUint32(a, v)
return a, nil
case uint64:
a := make([]byte, 8)
b.PutUint64(a, v)
return a, nil
case int:
switch true {
case v < 0:
return []byte{}, errNegativeNotAllowed
case v <= math.MaxUint32:
a := make([]byte, 4)
b.PutUint32(a, uint32(v))
return a, nil
default:
a := make([]byte, 8)
b.PutUint64(a, uint64(v))
return a, nil
}
case uint:
switch true {
case v < 0:
return []byte{}, errNegativeNotAllowed
case v <= math.MaxUint32:
a := make([]byte, 4)
b.PutUint32(a, uint32(v))
return a, nil
case v <= math.MaxUint64:
a := make([]byte, 8)
b.PutUint64(a, uint64(v))
return a, nil
default:
return []byte{}, fmt.Errorf("unable to cast %#v of type %T to []byte", i, i)
}
case string:
return []byte(v), nil
default:
return []byte{}, fmt.Errorf("unable to cast %#v of type %T to []byte", i, i)
}
}
// ToDurationSliceE casts an interface to a []time.Duration type.
func ToDurationSliceE(i interface{}) ([]time.Duration, error) {
if i == nil {