Skip to content

Commit

Permalink
documentation and flag support for DEFAULT, LENGTH, and ABS
Browse files Browse the repository at this point in the history
  • Loading branch information
mkenney committed Mar 7, 2024
1 parent 9af56d8 commit e9c148f
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 145 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
go.sum
vendor/
vendor/
_*
58 changes: 38 additions & 20 deletions to.array.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,28 @@ import (
"github.com/bdlm/errors/v2"
)

// toArray returns a slice containing the specified reflect.Value type with a length of
// 1 containing the from value.
func toArray(to reflect.Value, from any) (any, error) {
// toArray returns a slice containing the specified reflect.Value type
// containing the from value.
//
// Options:
// - DEFAULT: slice, default return value on error.
// - LENGTH: int, size of the backing array length, default 1. Must be greater
// than 0.
func toArray(to reflect.Value, from any, ops Ops) (any, error) {
var ret any
var ok bool

if _, ok = ops[DEFAULT]; ok {
ret = ops[DEFAULT]
}

size := 1
if _, ok = ops[LENGTH]; ok {
size = To[int](ops[LENGTH])
}
if !ok || size < 0 {
return ret, errors.Errorf("invalid channel buffer size %d", size)
}

switch to.Type().Elem().Kind() {
//case reflect.Invalid:
Expand Down Expand Up @@ -39,119 +57,119 @@ func toArray(to reflect.Value, from any) (any, error) {
if err != nil {
return ret, err
}
ret = make([]bool, 1)
ret = make([]bool, size)
ret = append(ret.([]bool), tval)
case reflect.Complex64:
tval, err := ToE[complex64](from)
if err != nil {
return ret, err
}
ret = make([]complex64, 1)
ret = make([]complex64, size)
ret = append(ret.([]complex64), tval)
case reflect.Complex128:
tval, err := ToE[complex128](from)
if err != nil {
return ret, err
}
ret = make([]complex128, 1)
ret = make([]complex128, size)
ret = append(ret.([]complex128), tval)
case reflect.Float32:
tval, err := ToE[float32](from)
if err != nil {
return ret, err
}
ret = make([]float32, 1)
ret = make([]float32, size)
ret = append(ret.([]float32), tval)
case reflect.Float64:
tval, err := ToE[float64](from)
if err != nil {
return ret, err
}
ret = make([]float64, 1)
ret = make([]float64, size)
ret = append(ret.([]float64), tval)
case reflect.Int:
tval, err := ToE[int](from)
if err != nil {
return ret, err
}
ret = make([]int, 1)
ret = make([]int, size)
ret = append(ret.([]int), tval)
case reflect.Int8:
tval, err := ToE[int8](from)
if err != nil {
return ret, err
}
ret = make([]int8, 1)
ret = make([]int8, size)
ret = append(ret.([]int8), tval)
case reflect.Int16:
tval, err := ToE[int16](from)
if err != nil {
return ret, err
}
ret = make([]int16, 1)
ret = make([]int16, size)
ret = append(ret.([]int16), tval)
case reflect.Int32:
tval, err := ToE[int32](from)
if err != nil {
return ret, err
}
ret = make([]int32, 1)
ret = make([]int32, size)
ret = append(ret.([]int32), tval)
case reflect.Int64:
tval, err := ToE[int64](from)
if err != nil {
return ret, err
}
ret = make([]int64, 1)
ret = make([]int64, size)
ret = append(ret.([]int64), tval)
case reflect.Uint:
tval, err := ToE[uint](from)
if err != nil {
return ret, err
}
ret = make([]uint, 1)
ret = make([]uint, size)
ret = append(ret.([]uint), tval)
case reflect.Uint8:
tval, err := ToE[uint8](from)
if err != nil {
return ret, err
}
ret = make([]uint8, 1)
ret = make([]uint8, size)
ret = append(ret.([]uint8), tval)
case reflect.Uint16:
tval, err := ToE[uint16](from)
if err != nil {
return ret, err
}
ret = make([]uint16, 1)
ret = make([]uint16, size)
ret = append(ret.([]uint16), tval)
case reflect.Uint32:
tval, err := ToE[uint32](from)
if err != nil {
return ret, err
}
ret = make([]uint32, 1)
ret = make([]uint32, size)
ret = append(ret.([]uint32), tval)
case reflect.Uint64:
tval, err := ToE[uint64](from)
if err != nil {
return ret, err
}
ret = make([]uint64, 1)
ret = make([]uint64, size)
ret = append(ret.([]uint64), tval)
case reflect.Uintptr:
tval, err := ToE[uintptr](from)
if err != nil {
return ret, err
}
ret = make([]uintptr, 1)
ret = make([]uintptr, size)
ret = append(ret.([]uintptr), tval)
case reflect.String:
tval, err := ToE[string](from)
if err != nil {
return ret, err
}
ret = make([]string, 1)
ret = make([]string, size)
ret = append(ret.([]string), tval)

}
Expand Down
42 changes: 27 additions & 15 deletions to.bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,54 @@ import (

// toBool casts an interface to a bool type. For numeric values, anything but
// zero is considered true.
//
// Options:
// - DEFAULT: bool, default false. Default return value on error.
func toBool[TTo bool](from any, ops Ops) (TTo, error) {
switch from.(type) {
var ret TTo
var ok bool

if _, ok = ops[DEFAULT]; ok {
if ret, ok = ops[DEFAULT].(TTo); !ok {
return false, errors.Errorf(ErrorInvalidOption, "DEFAULT", ops[DEFAULT])
}
}

switch from := from.(type) {
case bool:
return from.(bool) != false, nil
return TTo(from), nil
case byte:
return from.(byte) != 0 && from.(byte) != '0', nil
return from != 0 && from != '0', nil
case complex64:
return from.(complex64) != 0, nil
return from != 0, nil
case complex128:
return from.(complex128) != 0, nil
return from != 0, nil
case float32:
return from.(float32) != 0, nil
return from != 0, nil
case float64:
return from.(float64) != 0, nil
return from != 0, nil
case int:
return from.(int) != 0, nil
return from != 0, nil
case int8:
return from.(int8) != 0, nil
return from != 0, nil
case int16:
return from.(int16) != 0, nil
return from != 0, nil
case int32: // rune
return from.(rune) != 0 && from.(rune) != '0', nil
return from != 0 && from != '0', nil
case int64:
return from.(int64) != 0, nil
return from != 0, nil
case nil:
return false, nil
case string:
r, e := strconv.ParseBool(from.(string))
r, e := strconv.ParseBool(from)
if nil != e {
i, e2 := ToE[int](from)
if nil != e2 {
return false, errors.Wrap(errors.WrapE(e2, e), ErrorStrUnableToCast, from, from, false)
return ret, errors.Wrap(errors.WrapE(e2, e), ErrorStrUnableToCast, from, from, false)
}
return i != 0, nil
}
return r != false, nil
return TTo(r), nil
}

return false, errors.Errorf(ErrorStrUnableToCast, from, from, false)
Expand Down
18 changes: 16 additions & 2 deletions to.chan.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,27 @@ import (
)

// toChan returns a channel of the specified reflect.Value type with a buffer of
// 1 containing the from value.
// LENGTH containing the from value.
//
// Options:
// - DEFAULT: channel, default return value on error.
// - LENGTH: int, channel buffer size, default 1. Must be greater than or
// equal to 0.
func toChan(to reflect.Value, from any, ops Ops) (any, error) {
var ret any
var ok bool

if _, ok = ops[DEFAULT]; ok {
ret = ops[DEFAULT]
}

size := 1
if _, ok := ops[LENGTH]; ok {
if _, ok = ops[LENGTH]; ok {
size = To[int](ops[LENGTH])
}
if size < 1 {
return ret, errors.Errorf("invalid channel buffer size %d", size)
}

switch to.Type().Elem().Kind() {
//case reflect.Invalid:
Expand Down
18 changes: 14 additions & 4 deletions to.complex.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,32 @@ import (
"golang.org/x/exp/constraints"
)

// toComplex64 casts an interface to a complex number.
// toComplex casts an interface to a complex number.
//
// Options:
// - DEFAULT: complex64 or complex128, default return value on error.
func toComplex[TTo constraints.Complex](from reflect.Value, ops Ops) (TTo, error) {
var nilval TTo
var ret TTo
var ok bool

if _, ok = ops[DEFAULT]; ok {
if ret, ok = ops[DEFAULT].(TTo); !ok {
return ret, errors.Errorf(ErrorInvalidOption, "DEFAULT", ops[DEFAULT])
}
}

to := reflect.Indirect(reflect.ValueOf(new(TTo)))
switch to.Type().Kind() {
case reflect.Complex64:
f, err := toFloat[float32](from, ops)
if nil != err {
return nilval, err
return ret, err
}
return TTo(complex(f, 0)), nil
case reflect.Complex128:
f, err := toFloat[float64](from, ops)
if nil != err {
return nilval, err
return ret, err
}
return TTo(complex(f, 0)), nil
}
Expand Down
43 changes: 14 additions & 29 deletions to.float.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,25 @@ import (
)

// toFloat casts an interface to a float type.
//
// Options:
// - DEFAULT: float32 or float64, default 0.0. Default return value on error.
func toFloat[TTo constraints.Float](from reflect.Value, ops Ops) (TTo, error) {
var ret TTo
var ok bool

if _, ok = ops[DEFAULT]; ok {
if ret, ok = ops[DEFAULT].(TTo); !ok {
return ret, errors.Errorf(ErrorInvalidOption, "DEFAULT", ops[DEFAULT])
}
}

fromVal := reflect.ValueOf(from)
if !fromVal.IsValid() || !fromVal.CanInterface() {
return TTo(0), errors.Errorf("unable to cast %#.10v of type %T to %T", from, from, TTo(0))
return ret, errors.Errorf("unable to cast %#.10v of type %T to %T", from, from, TTo(0))
}

errDetail := errors.Errorf("unable to cast %#.10v of type %T to %T", from.Interface(), from.Interface(), TTo(0))
to := reflect.Indirect(reflect.ValueOf(new(TTo)))
unsigned := false
switch to.Interface().(type) {
case uint, uint8, uint16, uint32, uint64, uintptr:
unsigned = true
}

switch typ := from.Interface().(type) {
case nil:
Expand All @@ -34,39 +40,18 @@ func toFloat[TTo constraints.Float](from reflect.Value, ops Ops) (TTo, error) {
}
return TTo(0), nil
case float64:
if unsigned && typ < 0 {
return 0, errors.WrapE(ErrorSignedToUnsigned, errDetail)
}
return TTo(typ), nil
case float32:
if unsigned && typ < 0 {
return 0, errors.WrapE(ErrorSignedToUnsigned, errDetail)
}
return TTo(typ), nil
case int:
if unsigned && typ < 0 {
return 0, errors.WrapE(ErrorSignedToUnsigned, errDetail)
}
return TTo(typ), nil
case int64:
if unsigned && typ < 0 {
return 0, errors.WrapE(ErrorSignedToUnsigned, errDetail)
}
return TTo(typ), nil
case int32:
if unsigned && typ < 0 {
return 0, errors.WrapE(ErrorSignedToUnsigned, errDetail)
}
return TTo(typ), nil
case int16:
if unsigned && typ < 0 {
return 0, errors.WrapE(ErrorSignedToUnsigned, errDetail)
}
return TTo(typ), nil
case int8:
if unsigned && typ < 0 {
return 0, errors.WrapE(ErrorSignedToUnsigned, errDetail)
}
return TTo(typ), nil
case uint:
return TTo(typ), nil
Expand All @@ -86,7 +71,7 @@ func toFloat[TTo constraints.Float](from reflect.Value, ops Ops) (TTo, error) {

ret, err := toFloat[TTo](reflect.ValueOf(fmt.Sprintf("%v", from.Interface())), ops)
if nil != err {
return 0, errors.Wrap(err, ErrorStrUnableToCast, from.Interface(), from.Interface(), to.Interface())
return ret, errors.Wrap(err, ErrorStrUnableToCast, from.Interface(), from.Interface(), to.Interface())
}
return ret, nil
}
Expand Down
Loading

0 comments on commit e9c148f

Please sign in to comment.