From 1885f8f7526c1b9270068dd3a4ed015a5c57ad8c Mon Sep 17 00:00:00 2001 From: Edelweiss-Snow <1759279542@qq.com> Date: Fri, 28 Oct 2022 19:49:06 +0800 Subject: [PATCH] Feature:(issue_1550):Add support Int64Slice by read toml config file --- altsrc/flag.go | 31 +++++++++++++++++++++++++++++++ altsrc/input_source_context.go | 1 + altsrc/json_source_context.go | 23 +++++++++++++++++++++++ altsrc/map_input_source.go | 29 +++++++++++++++++++++++++++++ altsrc/map_input_source_test.go | 11 +++++++++++ 5 files changed, 95 insertions(+) diff --git a/altsrc/flag.go b/altsrc/flag.go index 8697b29d0a..d8256d7605 100644 --- a/altsrc/flag.go +++ b/altsrc/flag.go @@ -148,6 +148,37 @@ func (f *IntSliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceC return nil } +// ApplyInputSourceValue applies a Int64Slice value if required +func (f *Int64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error { + if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { + return nil + } + for _, name := range f.Int64SliceFlag.Names() { + if !isc.isSet(name) { + continue + } + value, err := isc.Int64Slice(name) + if err != nil { + return err + } + if value == nil { + continue + } + var sliceValue = *(cli.NewInt64Slice(value...)) + for _, n := range f.Names() { + underlyingFlag := f.set.Lookup(n) + if underlyingFlag == nil { + continue + } + underlyingFlag.Value = &sliceValue + } + if f.Destination != nil { + f.Destination.Set(sliceValue.Serialize()) + } + } + return nil +} + // ApplyInputSourceValue applies a Bool value to the flagSet if required func (f *BoolFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error { if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { diff --git a/altsrc/input_source_context.go b/altsrc/input_source_context.go index d743253050..24579d16a9 100644 --- a/altsrc/input_source_context.go +++ b/altsrc/input_source_context.go @@ -20,6 +20,7 @@ type InputSourceContext interface { String(name string) (string, error) StringSlice(name string) ([]string, error) IntSlice(name string) ([]int, error) + Int64Slice(name string) ([]int64, error) Generic(name string) (cli.Generic, error) Bool(name string) (bool, error) diff --git a/altsrc/json_source_context.go b/altsrc/json_source_context.go index 168b6dade0..ac0532076c 100644 --- a/altsrc/json_source_context.go +++ b/altsrc/json_source_context.go @@ -160,6 +160,29 @@ func (x *jsonSource) IntSlice(name string) ([]int, error) { } } +func (x *jsonSource) Int64Slice(name string) ([]int64, error) { + i, err := x.getValue(name) + if err != nil { + return nil, err + } + switch v := i.(type) { + default: + return nil, fmt.Errorf("unexpected type %T for %q", i, name) + case []int64: + return v, nil + case []interface{}: + c := []int64{} + for _, s := range v { + if i2, ok := s.(int64); ok { + c = append(c, i2) + } else { + return c, fmt.Errorf("unexpected item type %T in %T for %q", s, c, name) + } + } + return c, nil + } +} + func (x *jsonSource) Generic(name string) (cli.Generic, error) { i, err := x.getValue(name) if err != nil { diff --git a/altsrc/map_input_source.go b/altsrc/map_input_source.go index 07de00fcc6..2505b270eb 100644 --- a/altsrc/map_input_source.go +++ b/altsrc/map_input_source.go @@ -207,6 +207,35 @@ func (fsm *MapInputSource) IntSlice(name string) ([]int, error) { return intSlice, nil } +// Int64Slice returns an []int64 from the map if it exists otherwise returns nil +func (fsm *MapInputSource) Int64Slice(name string) ([]int64, error) { + otherGenericValue, exists := fsm.valueMap[name] + if !exists { + otherGenericValue, exists = nestedVal(name, fsm.valueMap) + if !exists { + return nil, nil + } + } + + otherValue, isType := otherGenericValue.([]interface{}) + if !isType { + return nil, incorrectTypeForFlagError(name, "[]interface{}", otherGenericValue) + } + + var int64Slice = make([]int64, 0, len(otherValue)) + for i, v := range otherValue { + int64Value, isType := v.(int64) + + if !isType { + return nil, incorrectTypeForFlagError(fmt.Sprintf("%s[%d]", name, i), "int", v) + } + + int64Slice = append(int64Slice, int64Value) + } + + return int64Slice, nil +} + // Generic returns an cli.Generic from the map if it exists otherwise returns nil func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) { otherGenericValue, exists := fsm.valueMap[name] diff --git a/altsrc/map_input_source_test.go b/altsrc/map_input_source_test.go index b90f796b30..cf399b5354 100644 --- a/altsrc/map_input_source_test.go +++ b/altsrc/map_input_source_test.go @@ -22,3 +22,14 @@ func TestMapDuration(t *testing.T) { _, err = inputSource.Duration("duration_of_int_type") refute(t, nil, err) } + +func TestMapInputSource_Int64Slice(t *testing.T) { + inputSource := NewMapInputSource( + "test", + map[interface{}]interface{}{ + "test_num": []interface{}{int64(1), int64(2), int64(3)}, + }) + d, err := inputSource.Int64Slice("test_num") + expect(t, []int64{1, 2, 3}, d) + expect(t, nil, err) +}