150 lines
3 KiB
Go
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())
|
|
}
|