| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- // Copyright 2012 Gary Burd
- //
- // Licensed under the Apache License, Version 2.0 (the "License"): you may
- // not use this file except in compliance with the License. You may obtain
- // a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- // License for the specific language governing permissions and limitations
- // under the License.
- package redis
- import (
- "errors"
- "fmt"
- "strconv"
- )
- var ErrNil = errors.New("redigo: nil returned")
- func Values(multiBulk []interface{}, values ...interface{}) ([]interface{}, error) {
- if len(multiBulk) < len(values) {
- return nil, errors.New("redigo Values: short multibulk")
- }
- var err error
- for i, value := range values {
- bulk := multiBulk[i]
- if bulk != nil {
- switch value := value.(type) {
- case *string:
- *value, err = String(bulk, nil)
- case *int:
- *value, err = Int(bulk, nil)
- case *bool:
- *value, err = Bool(bulk, nil)
- case *[]byte:
- *value, err = Bytes(bulk, nil)
- default:
- panic("Value type not supported")
- }
- if err != nil {
- break
- }
- }
- }
- return multiBulk[len(values):], err
- }
- // Int is a helper that converts a Redis reply to an int.
- //
- // Reply type Result
- // integer return reply as int
- // bulk parse decimal integer from reply
- // nil return error ErrNil
- // other return error
- //
- func Int(v interface{}, err error) (int, error) {
- if err != nil {
- return 0, err
- }
- switch v := v.(type) {
- case int64:
- return int(v), nil
- case []byte:
- n, err := strconv.ParseInt(string(v), 10, 0)
- return int(n), err
- case nil:
- return 0, ErrNil
- case Error:
- return 0, v
- }
- return 0, fmt.Errorf("redigo: unexpected type for Int, got type %T", v)
- }
- // String is a helper that converts a Redis reply to a string.
- //
- // Reply type Result
- // integer format as decimal string
- // bulk return reply as string
- // string return as is
- // nil return error ErrNil
- // other return error
- func String(v interface{}, err error) (string, error) {
- if err != nil {
- return "", err
- }
- switch v := v.(type) {
- case []byte:
- return string(v), nil
- case string:
- return v, nil
- case int64:
- return strconv.FormatInt(v, 10), nil
- case nil:
- return "", ErrNil
- case Error:
- return "", v
- }
- return "", fmt.Errorf("redigo: unexpected type for String, got type %T", v)
- }
- // Bytes is a helper that converts a Redis reply to slice of bytes.
- //
- // Reply type Result
- // integer format as decimal string
- // bulk return reply as slice of bytes
- // string return reply as slice of bytes
- // nil return error ErrNil
- // other return error
- func Bytes(v interface{}, err error) ([]byte, error) {
- if err != nil {
- return nil, err
- }
- switch v := v.(type) {
- case []byte:
- return v, nil
- case string:
- return []byte(v), nil
- case int64:
- return strconv.AppendInt(nil, v, 10), nil
- case nil:
- return nil, ErrNil
- case Error:
- return nil, v
- }
- return nil, fmt.Errorf("redigo: unexpected type for Bytes, got type %T", v)
- }
- // Bool is a helper that converts a Redis reply to a bool.
- //
- // Reply type Result
- // integer return value != 0
- // bulk return false if reply is "" or "0", otherwise return true.
- // nil return error ErrNil
- // other return error
- func Bool(v interface{}, err error) (bool, error) {
- if err != nil {
- return false, err
- }
- switch v := v.(type) {
- case int64:
- return v != 0, nil
- case []byte:
- if len(v) == 0 || (len(v) == 1 && v[0] == '0') {
- return false, nil
- }
- return true, nil
- case nil:
- return false, ErrNil
- case Error:
- return false, v
- }
- return false, fmt.Errorf("redigo: unexpected type for Bool, got type %T", v)
- }
- // MultiBulk is a helper that converts a Redis reply to a []interface{}.
- //
- // Reply type Result
- // multi-bulk return []interface{}
- // nil return error ErrNil
- // other return error
- func MultiBulk(v interface{}, err error) ([]interface{}, error) {
- if err != nil {
- return nil, err
- }
- switch v := v.(type) {
- case []interface{}:
- return v, nil
- case nil:
- return nil, ErrNil
- case Error:
- return nil, v
- }
- return nil, fmt.Errorf("redigo: unexpected type for MultiBulk, got type %T", v)
- }
- // Subscribe represents a subscribe or unsubscribe notification.
- type Subscription struct {
- // Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe"
- Kind string
- // The channel that was changed.
- Channel string
- // The current number of subscriptions for connection.
- Count int
- }
- // Message represents a message notification.
- type Message struct {
- // The originating channel.
- Channel string
- // The message data.
- Data []byte
- }
- // Notification is a helper that returns a pub/sub notification as a
- // Subscription or a Message.
- func Notification(reply interface{}, err error) (interface{}, error) {
- multiBulk, err := MultiBulk(reply, err)
- if err != nil {
- return nil, err
- }
- var kind, channel string
- multiBulk, err = Values(multiBulk, &kind, &channel)
- if err != nil {
- return nil, err
- }
- if kind == "message" {
- var data []byte
- if _, err := Values(multiBulk, &data); err != nil {
- return nil, err
- }
- return Message{channel, data}, nil
- }
- var count int
- if _, err := Values(multiBulk, &count); err != nil {
- return nil, err
- }
- return Subscription{kind, channel, count}, nil
- }
|