forked from cerc-io/ipld-eth-server
99 lines
2.3 KiB
Go
99 lines
2.3 KiB
Go
|
// Copyright (c) 2015 Arista Networks, Inc.
|
||
|
// Use of this source code is governed by the Apache License 2.0
|
||
|
// that can be found in the COPYING file.
|
||
|
|
||
|
package key
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"math"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/aristanetworks/goarista/value"
|
||
|
)
|
||
|
|
||
|
// StringifyInterface transforms an arbitrary interface into its string
|
||
|
// representation. We need to do this because some entities use the string
|
||
|
// representation of their keys as their names.
|
||
|
// Note: this API is deprecated and will be removed.
|
||
|
func StringifyInterface(key interface{}) (string, error) {
|
||
|
if key == nil {
|
||
|
return "", errors.New("Unable to stringify nil")
|
||
|
}
|
||
|
var str string
|
||
|
switch key := key.(type) {
|
||
|
case bool:
|
||
|
str = strconv.FormatBool(key)
|
||
|
case uint8:
|
||
|
str = strconv.FormatUint(uint64(key), 10)
|
||
|
case uint16:
|
||
|
str = strconv.FormatUint(uint64(key), 10)
|
||
|
case uint32:
|
||
|
str = strconv.FormatUint(uint64(key), 10)
|
||
|
case uint64:
|
||
|
str = strconv.FormatUint(key, 10)
|
||
|
case int8:
|
||
|
str = strconv.FormatInt(int64(key), 10)
|
||
|
case int16:
|
||
|
str = strconv.FormatInt(int64(key), 10)
|
||
|
case int32:
|
||
|
str = strconv.FormatInt(int64(key), 10)
|
||
|
case int64:
|
||
|
str = strconv.FormatInt(key, 10)
|
||
|
case float32:
|
||
|
str = "f" + strconv.FormatInt(int64(math.Float32bits(key)), 10)
|
||
|
case float64:
|
||
|
str = "f" + strconv.FormatInt(int64(math.Float64bits(key)), 10)
|
||
|
case string:
|
||
|
str = escape(key)
|
||
|
case map[string]interface{}:
|
||
|
keys := SortedKeys(key)
|
||
|
for i, k := range keys {
|
||
|
v := key[k]
|
||
|
keys[i] = stringify(v)
|
||
|
}
|
||
|
str = strings.Join(keys, "_")
|
||
|
case *map[string]interface{}:
|
||
|
return StringifyInterface(*key)
|
||
|
case map[Key]interface{}:
|
||
|
m := make(map[string]interface{}, len(key))
|
||
|
for k, v := range key {
|
||
|
m[k.String()] = v
|
||
|
}
|
||
|
keys := SortedKeys(m)
|
||
|
for i, k := range keys {
|
||
|
keys[i] = stringify(k) + "=" + stringify(m[k])
|
||
|
}
|
||
|
str = strings.Join(keys, "_")
|
||
|
|
||
|
case value.Value:
|
||
|
return key.String(), nil
|
||
|
|
||
|
default:
|
||
|
panic(fmt.Errorf("Unable to stringify type %T: %#v", key, key))
|
||
|
}
|
||
|
|
||
|
return str, nil
|
||
|
}
|
||
|
|
||
|
func escape(str string) string {
|
||
|
for i := 0; i < len(str); i++ {
|
||
|
if chr := str[i]; chr < 0x20 || chr > 0x7E {
|
||
|
str = strconv.QuoteToASCII(str)
|
||
|
str = str[1 : len(str)-1] // Drop the leading and trailing quotes.
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
return str
|
||
|
}
|
||
|
|
||
|
func stringify(key interface{}) string {
|
||
|
s, err := StringifyInterface(key)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
return s
|
||
|
}
|