drone-matrix/vendor/github.com/aymerick/raymond/string.go
2018-01-08 09:54:13 +01:00

85 lines
2.1 KiB
Go

package raymond
import (
"fmt"
"reflect"
"strconv"
)
// SafeString represents a string that must not be escaped.
//
// A SafeString can be returned by helpers to disable escaping.
type SafeString string
// isSafeString returns true if argument is a SafeString
func isSafeString(value interface{}) bool {
if _, ok := value.(SafeString); ok {
return true
}
return false
}
// Str returns string representation of any basic type value.
func Str(value interface{}) string {
return strValue(reflect.ValueOf(value))
}
// strValue returns string representation of a reflect.Value
func strValue(value reflect.Value) string {
result := ""
ival, ok := printableValue(value)
if !ok {
panic(fmt.Errorf("Can't print value: %q", value))
}
val := reflect.ValueOf(ival)
switch val.Kind() {
case reflect.Array, reflect.Slice:
for i := 0; i < val.Len(); i++ {
result += strValue(val.Index(i))
}
case reflect.Bool:
result = "false"
if val.Bool() {
result = "true"
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
result = fmt.Sprintf("%d", ival)
case reflect.Float32, reflect.Float64:
result = strconv.FormatFloat(val.Float(), 'f', -1, 64)
case reflect.Invalid:
result = ""
default:
result = fmt.Sprintf("%s", ival)
}
return result
}
// printableValue returns the, possibly indirected, interface value inside v that
// is best for a call to formatted printer.
//
// NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go
func printableValue(v reflect.Value) (interface{}, bool) {
if v.Kind() == reflect.Ptr {
v, _ = indirect(v) // fmt.Fprint handles nil.
}
if !v.IsValid() {
return "", true
}
if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) {
v = v.Addr()
} else {
switch v.Kind() {
case reflect.Chan, reflect.Func:
return nil, false
}
}
}
return v.Interface(), true
}