tdb/stringy/stringy.go
2020-04-15 23:53:50 -05:00

150 lines
3 KiB
Go

// Package stringy implements string conversion helpers for tdb
package stringy
import (
"encoding/base64"
"fmt"
//"log"
"reflect"
"strconv"
"strings"
)
var Serializers = map[reflect.Kind]func(reflect.Value) string{
reflect.Uint: UintToString,
reflect.Uint64: UintToString,
reflect.Uint32: UintToString,
reflect.Uint16: UintToString,
reflect.Uint8: UintToString,
reflect.Int: IntToString,
reflect.Int64: IntToString,
reflect.Int32: IntToString,
reflect.Int16: IntToString,
reflect.Int8: IntToString,
reflect.Float64: FloatToString,
reflect.Float32: FloatToString,
reflect.String: StringToString,
}
func ToString(v interface{}) (string, error) {
return ValToString(reflect.ValueOf(v))
}
func ToStringOrPanic(v interface{}) string {
s, err := ValToString(reflect.ValueOf(v))
if err != nil {
panic(err)
}
return s
}
func ValToString(val reflect.Value) (string, error) {
switch v := val.Interface().(type) {
case bool:
panic("unimplemented")
case float32:
case float64:
return FloatToString(val), nil
case complex64:
case complex128:
panic("unimplemented")
case int:
case int8:
case int16:
case int32:
case int64:
return IntToString(val), nil
case uint:
case uint8:
case uint16:
case uint32:
case uint64:
return UintToString(val), nil
case uintptr:
panic("unimplemented")
case string:
return StringToString(val), nil
case []byte:
return BytesToString(v), nil
}
valType := val.Type()
kind := valType.Kind()
if kind == reflect.Ptr {
return ptrToString(val)
}
if kind == reflect.Slice || kind == reflect.Array {
return indexableToString(val)
}
s, ok := Serializers[kind]
if !ok {
return "", fmt.Errorf("Unable to convert kind '%s' / type '%s' to string", kind.String(), valType.String())
}
return s(val), nil
}
func ValToStringOrPanic(val reflect.Value) string {
s, err := ValToString(val)
if err != nil {
panic(err)
}
return s
}
func LiteralIntToString(v int64) string {
return fmt.Sprintf("%+020d", v)
}
func IntToString(val reflect.Value) string {
return LiteralIntToString(val.Int())
}
func LiteralUintToString(v uint64) string {
return fmt.Sprintf("%020d", v)
}
func UintToString(val reflect.Value) string {
return LiteralUintToString(val.Uint())
}
func FloatToString(val reflect.Value) string {
return strconv.FormatFloat(val.Float(), 'E', -1, 64)
}
func BoolToString(val interface{}) string {
v, _ := val.(bool)
return strconv.FormatBool(v)
}
func StringToString(val reflect.Value) string {
return val.String()
}
func BytesToString(val []byte) string {
return base64.RawURLEncoding.EncodeToString(val)
}
func indexableToString(val reflect.Value) (string, error) {
l := val.Len()
items := make([]string, l)
for i := 0; i < l; i++ {
str, err := ValToString(val.Index(i))
if err != nil {
return "", err
}
items[i] = str
}
return "[" + strings.Join(items, ",") + "]", nil
}
func ptrToString(val reflect.Value) (string, error) {
if val.IsNil() {
return "nil", nil
}
return ValToString(val.Elem())
}