1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
package cli
import (
"encoding/json"
"fmt"
"reflect"
"strings"
)
// SliceBase wraps []T to satisfy flag.Value
type SliceBase[T any, C any, VC ValueCreator[T, C]] struct {
slice *[]T
hasBeenSet bool
value Value
}
func (i SliceBase[T, C, VC]) Create(val []T, p *[]T, c C) Value {
*p = []T{}
*p = append(*p, val...)
var t T
np := new(T)
var vc VC
return &SliceBase[T, C, VC]{
slice: p,
value: vc.Create(t, np, c),
}
}
// NewSliceBase makes a *SliceBase with default values
func NewSliceBase[T any, C any, VC ValueCreator[T, C]](defaults ...T) *SliceBase[T, C, VC] {
return &SliceBase[T, C, VC]{
slice: &defaults,
}
}
// Set parses the value and appends it to the list of values
func (i *SliceBase[T, C, VC]) Set(value string) error {
if !i.hasBeenSet {
*i.slice = []T{}
i.hasBeenSet = true
}
if strings.HasPrefix(value, slPfx) {
// Deserializing assumes overwrite
_ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice)
i.hasBeenSet = true
return nil
}
for _, s := range flagSplitMultiValues(value) {
if err := i.value.Set(strings.TrimSpace(s)); err != nil {
return err
}
*i.slice = append(*i.slice, i.value.Get().(T))
}
return nil
}
// String returns a readable representation of this value (for usage defaults)
func (i *SliceBase[T, C, VC]) String() string {
v := i.Value()
var t T
if reflect.TypeOf(t).Kind() == reflect.String {
return fmt.Sprintf("%v", v)
}
return fmt.Sprintf("%T{%s}", v, i.ToString(v))
}
// Serialize allows SliceBase to fulfill Serializer
func (i *SliceBase[T, C, VC]) Serialize() string {
jsonBytes, _ := json.Marshal(i.slice)
return fmt.Sprintf("%s%s", slPfx, string(jsonBytes))
}
// Value returns the slice of values set by this flag
func (i *SliceBase[T, C, VC]) Value() []T {
if i.slice == nil {
return nil
}
return *i.slice
}
// Get returns the slice of values set by this flag
func (i *SliceBase[T, C, VC]) Get() interface{} {
return *i.slice
}
func (i SliceBase[T, C, VC]) ToString(t []T) string {
var defaultVals []string
var v VC
for _, s := range t {
defaultVals = append(defaultVals, v.ToString(s))
}
return strings.Join(defaultVals, ", ")
}
|