// 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()) }