Skip to content

Commit

Permalink
Merge pull request #31 from rueian/include-nil-in-slice-conv
Browse files Browse the repository at this point in the history
feat: relax AsInt64 and AsFloat64, include nil as zero in slice conv …
  • Loading branch information
rueian authored May 8, 2022
2 parents 35c04b8 + 5d71144 commit 19cce92
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 24 deletions.
39 changes: 19 additions & 20 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ func (m *RedisMessage) DecodeJSON(v interface{}) (err error) {

// AsInt64 check if message is a redis string response, and parse it as int64
func (m *RedisMessage) AsInt64() (val int64, err error) {
if m.typ == ':' {
return m.integer, nil
}
v, err := m.ToString()
if err != nil {
return 0, err
Expand Down Expand Up @@ -355,6 +358,9 @@ func (m *RedisMessage) AsBool() (val bool, err error) {

// AsFloat64 check if message is a redis string response, and parse it as float64
func (m *RedisMessage) AsFloat64() (val float64, err error) {
if m.typ == ',' {
return strconv.ParseFloat(m.string, 64)
}
v, err := m.ToString()
if err != nil {
return 0, err
Expand Down Expand Up @@ -411,55 +417,50 @@ func (m *RedisMessage) ToArray() ([]RedisMessage, error) {
}

// AsStrSlice check if message is a redis array/set response, and convert to []string.
// Non string value will be ignored, including nil value.
// redis nil element and other non string element will be present as zero.
func (m *RedisMessage) AsStrSlice() ([]string, error) {
values, err := m.ToArray()
if err != nil {
return nil, err
}
s := make([]string, 0, len(values))
for _, v := range values {
if v.typ == '$' || v.typ == '+' || len(v.string) != 0 {
s = append(s, v.string)
}
s = append(s, v.string)
}
return s, nil
}

// AsIntSlice check if message is a redis array/set response, and convert to []int64.
// Non int value will be ignored, including nil value.
// redis nil element and other non integer element will be present as zero.
func (m *RedisMessage) AsIntSlice() ([]int64, error) {
values, err := m.ToArray()
if err != nil {
return nil, err
}
s := make([]int64, 0, len(values))
for _, v := range values {
if v.typ == ':' {
s = append(s, v.integer)
}
s = append(s, v.integer)
}
return s, nil
}

// AsFloatSlice check if message is a redis array/set response, and convert to []float64.
// Non float, int or string value will be ignored, including nil value.
// redis nil element and other non float element will be present as zero.
func (m *RedisMessage) AsFloatSlice() ([]float64, error) {
values, err := m.ToArray()
if err != nil {
return nil, err
}
s := make([]float64, 0, len(values))
for _, v := range values {
switch v.typ {
case ':':
s = append(s, float64(v.integer))
case ',', '$', '+':
if len(v.string) != 0 {
i, err := strconv.ParseFloat(v.string, 64)
if err != nil {
return nil, err
}
s = append(s, i)
} else {
s = append(s, float64(v.integer))
}
}
return s, nil
Expand Down Expand Up @@ -522,7 +523,7 @@ func (m *RedisMessage) AsMap() (map[string]RedisMessage, error) {
}

// AsStrMap check if message is a redis map/array/set response, and convert to map[string]string.
// Non string value will be ignored, including nil value.
// redis nil element and other non string element will be present as zero.
func (m *RedisMessage) AsStrMap() (map[string]string, error) {
if err := m.Error(); err != nil {
return nil, err
Expand All @@ -532,9 +533,7 @@ func (m *RedisMessage) AsStrMap() (map[string]string, error) {
for i := 0; i < len(m.values); i += 2 {
k := m.values[i]
v := m.values[i+1]
if (k.typ == '$' || k.typ == '+') && (v.typ == '$' || v.typ == '+' || len(v.string) != 0) {
r[k.string] = v.string
}
r[k.string] = v.string
}
return r, nil
}
Expand All @@ -543,7 +542,7 @@ func (m *RedisMessage) AsStrMap() (map[string]string, error) {
}

// AsIntMap check if message is a redis map/array/set response, and convert to map[string]int64.
// Non int or string value will be ignored, including nil value.
// redis nil element and other non integer element will be present as zero.
func (m *RedisMessage) AsIntMap() (map[string]int64, error) {
if err := m.Error(); err != nil {
return nil, err
Expand All @@ -555,11 +554,11 @@ func (m *RedisMessage) AsIntMap() (map[string]int64, error) {
k := m.values[i]
v := m.values[i+1]
if k.typ == '$' || k.typ == '+' {
if v.typ == '$' || v.typ == '+' || len(v.string) != 0 {
if len(v.string) != 0 {
if r[k.string], err = strconv.ParseInt(v.string, 0, 64); err != nil {
return nil, err
}
} else if v.typ == ':' {
} else if v.typ == ':' || v.typ == '_' {
r[k.string] = v.integer
}
}
Expand Down
14 changes: 10 additions & 4 deletions message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ func TestRedisResult(t *testing.T) {
if v, _ := (RedisResult{val: RedisMessage{typ: '+', string: "1"}}).AsInt64(); v != 1 {
t.Fatal("AsInt64 not get value as expected")
}
if v, _ := (RedisResult{val: RedisMessage{typ: ':', integer: 2}}).AsInt64(); v != 2 {
t.Fatal("AsInt64 not get value as expected")
}
})

t.Run("AsFloat64", func(t *testing.T) {
Expand All @@ -139,7 +142,10 @@ func TestRedisResult(t *testing.T) {
if _, err := (RedisResult{val: RedisMessage{typ: '-'}}).AsFloat64(); err == nil {
t.Fatal("AsFloat64 not failed as expected")
}
if v, _ := (RedisResult{val: RedisMessage{typ: '+', string: "1"}}).AsFloat64(); v != 1 {
if v, _ := (RedisResult{val: RedisMessage{typ: '+', string: "1.1"}}).AsFloat64(); v != 1.1 {
t.Fatal("AsFloat64 not get value as expected")
}
if v, _ := (RedisResult{val: RedisMessage{typ: ',', string: "2.2"}}).AsFloat64(); v != 2.2 {
t.Fatal("AsFloat64 not get value as expected")
}
})
Expand Down Expand Up @@ -190,7 +196,7 @@ func TestRedisResult(t *testing.T) {
if _, err := (RedisResult{val: RedisMessage{typ: '-'}}).AsFloatSlice(); err == nil {
t.Fatal("AsFloatSlice not failed as expected")
}
if _, err := (RedisResult{val: RedisMessage{typ: '*', values: []RedisMessage{{string: "", typ: ','}}}}).AsFloatSlice(); err == nil {
if _, err := (RedisResult{val: RedisMessage{typ: '*', values: []RedisMessage{{string: "fff", typ: ','}}}}).AsFloatSlice(); err == nil {
t.Fatal("AsFloatSlice not failed as expected")
}
values := []RedisMessage{{integer: 1, typ: ':'}, {string: "2", typ: '+'}, {string: "3", typ: '$'}, {string: "4", typ: ','}}
Expand Down Expand Up @@ -434,11 +440,11 @@ func TestRedisMessage(t *testing.T) {
t.Fatal("AsInt64 not failed as expected")
}
defer func() {
if !strings.Contains(recover().(string), "redis message type : is not a string") {
if !strings.Contains(recover().(string), "redis message type * is not a string") {
t.Fatal("AsInt64 not panic as expected")
}
}()
(&RedisMessage{typ: ':'}).AsInt64()
(&RedisMessage{typ: '*', values: []RedisMessage{{}}}).AsInt64()
})

t.Run("AsFloat64", func(t *testing.T) {
Expand Down

0 comments on commit 19cce92

Please sign in to comment.