Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,20 +794,33 @@ func counterMapper() MapperFunc {
if err != nil {
return err
}
var n int64
switch v := t.Value.(type) {
case string:
n, err := strconv.ParseInt(v, 10, 64)
n, err = strconv.ParseInt(v, 10, 64)
if err != nil {
return fmt.Errorf("expected a counter but got %q (%T)", t, t.Value)
}
target.SetInt(n)

case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
target.Set(reflect.ValueOf(v))
n = reflect.ValueOf(v).Convert(reflect.TypeOf(int64(0))).Int()

default:
return fmt.Errorf("expected a counter but got %q (%T)", t, t.Value)
}

// Assign by the target's kind, like the increment path below, so a
// counter declared as a uint or float field doesn't panic.
switch target.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
target.SetInt(n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
target.SetUint(uint64(n)) //nolint:gosec // a counter value is small and non-negative
case reflect.Float32, reflect.Float64:
target.SetFloat(float64(n))
default:
return fmt.Errorf("type:\"counter\" must be used with a numeric field")
}
return nil
}

Expand Down
10 changes: 10 additions & 0 deletions mapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,16 @@ func TestCounter(t *testing.T) {
_, err = p.Parse([]string{"-fff"})
assert.NoError(t, err)
assert.Equal(t, 3., cli.Float)

// Explicit --long=N on a uint or float counter must not panic (only the
// int field was covered before; uint/float went through SetInt).
_, err = p.Parse([]string{"--uint=5"})
assert.NoError(t, err)
assert.Equal(t, uint(5), cli.Uint)

_, err = p.Parse([]string{"--float=5"})
assert.NoError(t, err)
assert.Equal(t, 5., cli.Float)
}

func TestNumbers(t *testing.T) {
Expand Down