mirror of
https://github.com/metabarcoding/obitools4.git
synced 2025-06-29 16:20:46 +00:00
299 lines
7.0 KiB
Go
299 lines
7.0 KiB
Go
package obiutils
|
|
|
|
import (
|
|
"fmt"
|
|
"maps"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// InterfaceToString converts an interface value to a string.
|
|
//
|
|
// The function takes an interface{} value as a parameter and returns a string representation of that value.
|
|
// It returns the string representation and an error if any occurred during the conversion process.
|
|
func InterfaceToString(i interface{}) (val string, err error) {
|
|
err = nil
|
|
if vc, ok := i.(interface{ String() string }); ok {
|
|
val = vc.String()
|
|
} else {
|
|
val = fmt.Sprintf("%v", i)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// CastableToInt checks if the given input can be casted to an integer.
|
|
//
|
|
// i: the value to check for castability.
|
|
// bool: true if the value can be casted to an integer, false otherwise.
|
|
func CastableToInt(i interface{}) bool {
|
|
switch i.(type) {
|
|
case int,
|
|
int8, int16, int32, int64,
|
|
float32, float64,
|
|
uint8, uint16, uint32, uint64:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// InterfaceToBool converts an interface value to a boolean.
|
|
//
|
|
// It takes an interface{} as a parameter and returns a boolean value and an error.
|
|
func InterfaceToBool(i interface{}) (val bool, err error) {
|
|
|
|
err = nil
|
|
val = false
|
|
|
|
switch t := i.(type) {
|
|
case bool:
|
|
val = t
|
|
case int:
|
|
val = t != 0
|
|
case int8:
|
|
val = t != 0 // standardizes across systems
|
|
case int16:
|
|
val = t != 0 // standardizes across systems
|
|
case int32:
|
|
val = t != 0 // standardizes across systems
|
|
case int64:
|
|
val = t != 0 // standardizes across systems
|
|
case float32:
|
|
val = t != 0 // standardizes across systems
|
|
case float64:
|
|
val = t != 0 // standardizes across systems
|
|
case uint8:
|
|
val = t != 0 // standardizes across systems
|
|
case uint16:
|
|
val = t != 0 // standardizes across systems
|
|
case uint32:
|
|
val = t != 0 // standardizes across systems
|
|
case uint64:
|
|
val = t != 0 // standardizes across systems
|
|
case string:
|
|
val = strings.ToLower(t) == "true" || t == "1" || strings.ToLower(t) == "yes" || strings.ToLower(t) == "on" || strings.ToLower(t) == "t"
|
|
case nil:
|
|
val = false
|
|
default:
|
|
err = &NotABoolean{"value attribute cannot be casted to a boolean"}
|
|
}
|
|
return
|
|
}
|
|
|
|
// MapToMapInterface converts a map to a map of type map[string]interface{}.
|
|
//
|
|
// It takes an interface{} parameter `m` which represents the map to be converted.
|
|
//
|
|
// It returns a map[string]interface{} which is the converted map. If the input map is not of type map[string]interface{},
|
|
// it panics and logs an error message.
|
|
func MapToMapInterface(m interface{}) map[string]interface{} {
|
|
type hasMap interface {
|
|
Map() map[string]int
|
|
RLock()
|
|
RUnlock()
|
|
Len() int
|
|
}
|
|
|
|
if v, ok := m.(hasMap); ok {
|
|
val := make(map[string]interface{}, v.Len())
|
|
v.RLock()
|
|
defer v.RUnlock()
|
|
for k, v := range v.Map() {
|
|
val[k] = v
|
|
}
|
|
} else if IsAMap(m) {
|
|
reflectMap := reflect.ValueOf(m)
|
|
keys := reflectMap.MapKeys()
|
|
val := make(map[string]interface{}, len(keys))
|
|
for k := range keys {
|
|
val[keys[k].String()] = reflectMap.MapIndex(keys[k]).Interface()
|
|
}
|
|
|
|
return val
|
|
}
|
|
|
|
log.Panic("Invalid map type")
|
|
return make(map[string]interface{})
|
|
}
|
|
|
|
// InterfaceToInt converts a interface{} to an integer value if possible.
|
|
// If not a "NotAnInteger" error is returned via the err
|
|
// return value and val is set to 0.
|
|
func InterfaceToInt(i interface{}) (val int, err error) {
|
|
|
|
err = nil
|
|
val = 0
|
|
|
|
switch t := i.(type) {
|
|
case int:
|
|
val = t
|
|
case int8:
|
|
val = int(t) // standardizes across systems
|
|
case int16:
|
|
val = int(t) // standardizes across systems
|
|
case int32:
|
|
val = int(t) // standardizes across systems
|
|
case int64:
|
|
val = int(t) // standardizes across systems
|
|
case float32:
|
|
val = int(t) // standardizes across systems
|
|
case float64:
|
|
val = int(t) // standardizes across systems
|
|
case uint8:
|
|
val = int(t) // standardizes across systems
|
|
case uint16:
|
|
val = int(t) // standardizes across systems
|
|
case uint32:
|
|
val = int(t) // standardizes across systems
|
|
case uint64:
|
|
val = int(t) // standardizes across systems
|
|
case string:
|
|
rep, err := strconv.ParseInt(t, 10, 64)
|
|
if err != nil {
|
|
err = &NotAnFloat64{"value attribute cannot be casted to an int value"}
|
|
}
|
|
val = int(rep)
|
|
default:
|
|
err = &NotAnInteger{"value attribute cannot be casted to an integer"}
|
|
}
|
|
return
|
|
}
|
|
|
|
// InterfaceToInt converts a interface{} to an integer value if possible.
|
|
// If not a "NotAnInteger" error is returned via the err
|
|
// return value and val is set to 0.
|
|
func InterfaceToFloat64(i interface{}) (val float64, err error) {
|
|
|
|
err = nil
|
|
val = 0
|
|
|
|
switch t := i.(type) {
|
|
case int:
|
|
val = float64(t)
|
|
case int8:
|
|
val = float64(t) // standardizes across systems
|
|
case int16:
|
|
val = float64(t) // standardizes across systems
|
|
case int32:
|
|
val = float64(t) // standardizes across systems
|
|
case int64:
|
|
val = float64(t) // standardizes across systems
|
|
case float32:
|
|
val = float64(t) // standardizes across systems
|
|
case float64:
|
|
val = t // standardizes across systems
|
|
case uint8:
|
|
val = float64(t) // standardizes across systems
|
|
case uint16:
|
|
val = float64(t) // standardizes across systems
|
|
case uint32:
|
|
val = float64(t) // standardizes across systems
|
|
case uint64:
|
|
val = float64(t) // standardizes across systems
|
|
case string:
|
|
val, err = strconv.ParseFloat(t, 10)
|
|
if err != nil {
|
|
err = &NotAnFloat64{"value attribute cannot be casted to a float value"}
|
|
}
|
|
default:
|
|
err = &NotAnFloat64{"value attribute cannot be casted to a float value"}
|
|
}
|
|
return
|
|
}
|
|
|
|
func InterfaceToIntMap(i interface{}) (val map[string]int, err error) {
|
|
err = nil
|
|
|
|
type hasMap interface {
|
|
Map() map[string]int
|
|
RLock()
|
|
RUnlock()
|
|
}
|
|
|
|
switch i := i.(type) {
|
|
case map[string]int:
|
|
val = i
|
|
case hasMap:
|
|
i.RLock()
|
|
defer i.RUnlock()
|
|
val = maps.Clone(i.Map())
|
|
case map[string]interface{}:
|
|
val = make(map[string]int, len(i))
|
|
for k, v := range i {
|
|
val[k], err = InterfaceToInt(v)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
case map[string]float64:
|
|
val = make(map[string]int, len(i))
|
|
for k, v := range i {
|
|
val[k] = int(v)
|
|
}
|
|
default:
|
|
err = &NotAMapInt{"value attribute cannot be casted to a map[string]int"}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func InterfaceToStringMap(i interface{}) (val map[string]string, err error) {
|
|
err = nil
|
|
|
|
type hasMap interface {
|
|
Map() map[string]int
|
|
RLock()
|
|
RUnlock()
|
|
Len() int
|
|
}
|
|
|
|
switch i := i.(type) {
|
|
case map[string]string:
|
|
val = i
|
|
case hasMap:
|
|
val = make(map[string]string, i.Len())
|
|
i.RLock()
|
|
defer i.RUnlock()
|
|
for k, v := range i.Map() {
|
|
val[k] = strconv.Itoa(v)
|
|
}
|
|
case map[string]interface{}:
|
|
val = make(map[string]string, len(i))
|
|
for k, v := range i {
|
|
val[k], err = InterfaceToString(v)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
default:
|
|
err = &NotAMapInt{"value attribute cannot be casted to a map[string]int"}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func InterfaceToStringSlice(i interface{}) (val []string, err error) {
|
|
err = nil
|
|
|
|
switch i := i.(type) {
|
|
case []string:
|
|
val = i
|
|
case []interface{}:
|
|
val = make([]string, len(i))
|
|
for k, v := range i {
|
|
val[k], err = InterfaceToString(v)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
default:
|
|
err = &NotAMapInt{"value attribute cannot be casted to a []string"}
|
|
}
|
|
|
|
return
|
|
}
|