Skip to content

Commit

Permalink
Merge pull request #1669 from kjeom/integerTypeCasting
Browse files Browse the repository at this point in the history
add Integer type casting when loading yaml file
  • Loading branch information
dearchap authored Feb 26, 2023
2 parents 2bd6319 + 963fab7 commit ce617c1
Show file tree
Hide file tree
Showing 3 changed files with 339 additions and 11 deletions.
1 change: 1 addition & 0 deletions altsrc/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func (f *StringSliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSour
continue
}
underlyingFlag.Value = &sliceValue
f.set.Set(n, sliceValue.Serialize())
}
if f.Destination != nil {
f.Destination.Set(sliceValue.Serialize())
Expand Down
106 changes: 96 additions & 10 deletions altsrc/map_input_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package altsrc

import (
"fmt"
"math"
"reflect"
"strings"
"time"
Expand Down Expand Up @@ -127,19 +128,39 @@ func (fsm *MapInputSource) Float64(name string) (float64, error) {
return 0, nil
}

func castToInt64(v interface{}) (int64, bool) {
int64Value := int64(0)
isType := false
if v == nil {
return int64Value, true
}

// There are only four cases(int, int64, uint64, float64) when parsing the integer in yaml.v3 pkg
// But the cases, uint64, float64, are an error case so that ignored
switch value := v.(type) {
case int:
int64Value = int64(value)
isType = true
case int64:
int64Value = int64(value)
isType = true
}
return int64Value, isType
}

// Int64 returns an int64 from the map if it exists otherwise returns 0
func (fsm *MapInputSource) Int64(name string) (int64, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(int64)
otherValue, isType := castToInt64(otherGenericValue)
if !isType {
return 0, incorrectTypeForFlagError(name, "int64", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(int64)
otherValue, isType := castToInt64(otherGenericValue)
if !isType {
return 0, incorrectTypeForFlagError(name, "int64", nestedGenericValue)
}
Expand All @@ -149,19 +170,54 @@ func (fsm *MapInputSource) Int64(name string) (int64, error) {
return 0, nil
}

func castToUint(v interface{}) (uint, bool) {
uintValue := uint(0)
isType := false
if v == nil {
return uintValue, true
}

// There are only four cases(int, int64, uint64, float64) when parsing the integer in yaml.v3 pkg
// But the last case, float64, is an error case so that ignored
switch value := v.(type) {
case int:
intValue := int(value)
if intValue >= 0 {
uintValue = uint(value)
isType = true
}
case int64:
int64Value := int64(value)
if int64Value >= 0 && uint64(int64Value) <= math.MaxUint {
uintValue = uint(value)
isType = true
}
case uint:
uintValue = uint(value)
isType = true
case uint64:
uint64Value := uint64(value)
if uint64Value <= math.MaxUint {
uintValue = uint(value)
isType = true
}
}
return uintValue, isType
}

// Int64 returns an int64 from the map if it exists otherwise returns 0
func (fsm *MapInputSource) Uint(name string) (uint, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(uint)
otherValue, isType := castToUint(otherGenericValue)
if !isType {
return 0, incorrectTypeForFlagError(name, "uint", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(uint)
otherValue, isType := castToUint(nestedGenericValue)
if !isType {
return 0, incorrectTypeForFlagError(name, "uint", nestedGenericValue)
}
Expand All @@ -171,19 +227,51 @@ func (fsm *MapInputSource) Uint(name string) (uint, error) {
return 0, nil
}

func castToUint64(v interface{}) (uint64, bool) {
uint64Value := uint64(0)
isType := false
if v == nil {
return uint64Value, true
}

// There are only four cases(int, int64, uint64, float64) when parsing the integer in yaml.v3 pkg
// But the last case, float64, is an error case so that ignored
switch value := v.(type) {
case int:
intValue := int(value)
if intValue >= 0 {
uint64Value = uint64(intValue)
isType = true
}
case int64:
int64Value := int64(value)
if int64Value >= 0 {
uint64Value = uint64(int64Value)
isType = true
}
case uint:
uint64Value = uint64(value)
isType = true
case uint64:
uint64Value = uint64(value)
isType = true
}
return uint64Value, isType
}

// UInt64 returns an uint64 from the map if it exists otherwise returns 0
func (fsm *MapInputSource) Uint64(name string) (uint64, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(uint64)
otherValue, isType := castToUint64(otherGenericValue)
if !isType {
return 0, incorrectTypeForFlagError(name, "uint64", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(uint64)
otherValue, isType := castToUint64(nestedGenericValue)
if !isType {
return 0, incorrectTypeForFlagError(name, "uint64", nestedGenericValue)
}
Expand Down Expand Up @@ -290,12 +378,10 @@ func (fsm *MapInputSource) Int64Slice(name string) ([]int64, error) {

var int64Slice = make([]int64, 0, len(otherValue))
for i, v := range otherValue {
int64Value, isType := v.(int64)

int64Value, isType := castToInt64(v)
if !isType {
return nil, incorrectTypeForFlagError(fmt.Sprintf("%s[%d]", name, i), "int", v)
return nil, incorrectTypeForFlagError(fmt.Sprintf("%s[%d]", name, i), "int64", v)
}

int64Slice = append(int64Slice, int64Value)
}

Expand Down
Loading

0 comments on commit ce617c1

Please sign in to comment.