From ef220d094414ea3cccddc538223b3568c4ca723c Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Sat, 5 Sep 2020 13:17:26 +0300 Subject: [PATCH] Tweak append arg --- internal/arg.go | 147 +++++++++++++++++++++++++++++++++++++++++++++++ internal/util.go | 74 ------------------------ 2 files changed, 147 insertions(+), 74 deletions(-) create mode 100644 internal/arg.go diff --git a/internal/arg.go b/internal/arg.go new file mode 100644 index 00000000..4f683393 --- /dev/null +++ b/internal/arg.go @@ -0,0 +1,147 @@ +package internal + +import ( + "encoding/hex" + "fmt" + "strconv" + "time" +) + +func AppendArg(b []byte, v interface{}) []byte { + switch v := v.(type) { + case nil: + return append(b, ""...) + case string: + return appendUTF8String(b, Bytes(v)) + case []byte: + return appendUTF8String(b, v) + case int: + return strconv.AppendInt(b, int64(v), 10) + case int8: + return strconv.AppendInt(b, int64(v), 10) + case int16: + return strconv.AppendInt(b, int64(v), 10) + case int32: + return strconv.AppendInt(b, int64(v), 10) + case int64: + return strconv.AppendInt(b, v, 10) + case uint: + return strconv.AppendUint(b, uint64(v), 10) + case uint8: + return strconv.AppendUint(b, uint64(v), 10) + case uint16: + return strconv.AppendUint(b, uint64(v), 10) + case uint32: + return strconv.AppendUint(b, uint64(v), 10) + case uint64: + return strconv.AppendUint(b, v, 10) + case float32: + return strconv.AppendFloat(b, float64(v), 'f', -1, 64) + case float64: + return strconv.AppendFloat(b, v, 'f', -1, 64) + case bool: + if v { + return append(b, "true"...) + } + return append(b, "false"...) + case time.Time: + return v.AppendFormat(b, time.RFC3339Nano) + default: + return append(b, fmt.Sprint(v)...) + } +} + +func appendUTF8String(dst []byte, src []byte) []byte { + if isSimple(src) { + dst = append(dst, src...) + return dst + } + + s := len(dst) + dst = append(dst, make([]byte, hex.EncodedLen(len(src)))...) + hex.Encode(dst[s:], src) + return dst +} + +func isSimple(b []byte) bool { + for _, c := range b { + if !isSimpleByte(c) { + return false + } + } + return true +} + +func isSimpleByte(c byte) bool { + return simple[c] +} + +var simple = [256]bool{ + '-': true, + '_': true, + + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + + 'a': true, + 'b': true, + 'c': true, + 'd': true, + 'e': true, + 'f': true, + 'g': true, + 'h': true, + 'i': true, + 'j': true, + 'k': true, + 'l': true, + 'm': true, + 'n': true, + 'o': true, + 'p': true, + 'q': true, + 'r': true, + 's': true, + 't': true, + 'u': true, + 'v': true, + 'w': true, + 'x': true, + 'y': true, + 'z': true, + + 'A': true, + 'B': true, + 'C': true, + 'D': true, + 'E': true, + 'F': true, + 'G': true, + 'H': true, + 'I': true, + 'J': true, + 'K': true, + 'L': true, + 'M': true, + 'N': true, + 'O': true, + 'P': true, + 'Q': true, + 'R': true, + 'S': true, + 'T': true, + 'U': true, + 'V': true, + 'W': true, + 'X': true, + 'Y': true, + 'Z': true, +} diff --git a/internal/util.go b/internal/util.go index 4f8549ec..710bfe14 100644 --- a/internal/util.go +++ b/internal/util.go @@ -2,10 +2,7 @@ package internal import ( "context" - "fmt" - "strconv" "time" - "unicode/utf8" "github.com/go-redis/redis/v8/internal/proto" "github.com/go-redis/redis/v8/internal/util" @@ -63,77 +60,6 @@ func Unwrap(err error) error { return u.Unwrap() } -func AppendArg(b []byte, v interface{}) []byte { - switch v := v.(type) { - case nil: - return append(b, ""...) - case string: - return appendUTF8String(b, v) - case []byte: - return appendUTF8String(b, String(v)) - case int: - return strconv.AppendInt(b, int64(v), 10) - case int8: - return strconv.AppendInt(b, int64(v), 10) - case int16: - return strconv.AppendInt(b, int64(v), 10) - case int32: - return strconv.AppendInt(b, int64(v), 10) - case int64: - return strconv.AppendInt(b, v, 10) - case uint: - return strconv.AppendUint(b, uint64(v), 10) - case uint8: - return strconv.AppendUint(b, uint64(v), 10) - case uint16: - return strconv.AppendUint(b, uint64(v), 10) - case uint32: - return strconv.AppendUint(b, uint64(v), 10) - case uint64: - return strconv.AppendUint(b, v, 10) - case float32: - return strconv.AppendFloat(b, float64(v), 'f', -1, 64) - case float64: - return strconv.AppendFloat(b, v, 'f', -1, 64) - case bool: - if v { - return append(b, "true"...) - } - return append(b, "false"...) - case time.Time: - return v.AppendFormat(b, time.RFC3339Nano) - default: - return append(b, fmt.Sprint(v)...) - } -} - -func appendUTF8String(b []byte, s string) []byte { - for _, r := range s { - b = appendRune(b, r) - } - return b -} - -func appendRune(b []byte, r rune) []byte { - if r < utf8.RuneSelf { - switch c := byte(r); c { - case '\n': - return append(b, "\\n"...) - case '\r': - return append(b, "\\r"...) - default: - return append(b, c) - } - } - - l := len(b) - b = append(b, make([]byte, utf8.UTFMax)...) - n := utf8.EncodeRune(b[l:l+utf8.UTFMax], r) - b = b[:l+n] - - return b -} - //------------------------------------------------------------------------------ func WithSpan(ctx context.Context, name string, fn func(context.Context) error) error {