cosmossdk.io/client/v2@v2.0.0-beta.1/autocli/flag/map.go (about)

     1  package flag
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/cockroachdb/errors"
     9  	"github.com/spf13/pflag"
    10  	"google.golang.org/protobuf/reflect/protoreflect"
    11  
    12  	"cosmossdk.io/client/v2/autocli/flag/maps"
    13  )
    14  
    15  func bindSimpleMapFlag(flagSet *pflag.FlagSet, keyKind, valueKind protoreflect.Kind, name, shorthand, usage string) HasValue {
    16  	switch keyKind {
    17  	case protoreflect.StringKind:
    18  		switch valueKind {
    19  		case protoreflect.StringKind:
    20  			val := flagSet.StringToStringP(name, shorthand, nil, usage)
    21  			return newMapValue(val, protoreflect.ValueOfString)
    22  		case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
    23  			val := maps.StringToInt32P(flagSet, name, shorthand, nil, usage)
    24  			return newMapValue(val, protoreflect.ValueOfInt32)
    25  		case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
    26  			val := flagSet.StringToInt64P(name, shorthand, nil, usage)
    27  			return newMapValue(val, protoreflect.ValueOfInt64)
    28  		case protoreflect.Uint32Kind:
    29  			val := maps.StringToUint32P(flagSet, name, shorthand, nil, usage)
    30  			return newMapValue(val, protoreflect.ValueOfUint32)
    31  		case protoreflect.Uint64Kind:
    32  			val := maps.StringToUint64P(flagSet, name, shorthand, nil, usage)
    33  			return newMapValue(val, protoreflect.ValueOfUint64)
    34  		case protoreflect.BoolKind:
    35  			val := maps.StringToBoolP(flagSet, name, shorthand, nil, usage)
    36  			return newMapValue(val, protoreflect.ValueOfBool)
    37  		}
    38  
    39  	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
    40  		switch valueKind {
    41  		case protoreflect.StringKind:
    42  			val := maps.Int32ToStringP(flagSet, name, shorthand, nil, usage)
    43  			return newMapValue(val, protoreflect.ValueOfString)
    44  		case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
    45  			val := maps.Int32ToInt32P(flagSet, name, shorthand, nil, usage)
    46  			return newMapValue(val, protoreflect.ValueOfInt32)
    47  		case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
    48  			val := maps.Int32ToInt64P(flagSet, name, shorthand, nil, usage)
    49  			return newMapValue(val, protoreflect.ValueOfInt64)
    50  		case protoreflect.Uint32Kind:
    51  			val := maps.Int32ToUint32P(flagSet, name, shorthand, nil, usage)
    52  			return newMapValue(val, protoreflect.ValueOfUint32)
    53  		case protoreflect.Uint64Kind:
    54  			val := maps.Int32ToUint64P(flagSet, name, shorthand, nil, usage)
    55  			return newMapValue(val, protoreflect.ValueOfUint64)
    56  		case protoreflect.BoolKind:
    57  			val := maps.Int32ToBoolP(flagSet, name, shorthand, nil, usage)
    58  			return newMapValue(val, protoreflect.ValueOfBool)
    59  		}
    60  
    61  	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
    62  		switch valueKind {
    63  		case protoreflect.StringKind:
    64  			val := maps.Int64ToStringP(flagSet, name, shorthand, nil, usage)
    65  			return newMapValue(val, protoreflect.ValueOfString)
    66  		case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
    67  			val := maps.Int64ToInt32P(flagSet, name, shorthand, nil, usage)
    68  			return newMapValue(val, protoreflect.ValueOfInt32)
    69  		case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
    70  			val := maps.Int64ToInt64P(flagSet, name, shorthand, nil, usage)
    71  			return newMapValue(val, protoreflect.ValueOfInt64)
    72  		case protoreflect.Uint32Kind:
    73  			val := maps.Int64ToUint32P(flagSet, name, shorthand, nil, usage)
    74  			return newMapValue(val, protoreflect.ValueOfUint32)
    75  		case protoreflect.Uint64Kind:
    76  			val := maps.Int64ToUint64P(flagSet, name, shorthand, nil, usage)
    77  			return newMapValue(val, protoreflect.ValueOfUint64)
    78  		case protoreflect.BoolKind:
    79  			val := maps.Int64ToBoolP(flagSet, name, shorthand, nil, usage)
    80  			return newMapValue(val, protoreflect.ValueOfBool)
    81  		}
    82  	case protoreflect.Uint32Kind:
    83  		switch valueKind {
    84  		case protoreflect.StringKind:
    85  			val := maps.Uint32ToStringP(flagSet, name, shorthand, nil, usage)
    86  			return newMapValue(val, protoreflect.ValueOfString)
    87  		case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
    88  			val := maps.Uint32ToInt32P(flagSet, name, shorthand, nil, usage)
    89  			return newMapValue(val, protoreflect.ValueOfInt32)
    90  		case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
    91  			val := maps.Uint32ToInt64P(flagSet, name, shorthand, nil, usage)
    92  			return newMapValue(val, protoreflect.ValueOfInt64)
    93  		case protoreflect.Uint32Kind:
    94  			val := maps.Uint32ToUint32P(flagSet, name, shorthand, nil, usage)
    95  			return newMapValue(val, protoreflect.ValueOfUint32)
    96  		case protoreflect.Uint64Kind:
    97  			val := maps.Uint32ToUint64P(flagSet, name, shorthand, nil, usage)
    98  			return newMapValue(val, protoreflect.ValueOfUint64)
    99  		case protoreflect.BoolKind:
   100  			val := maps.Uint32ToBoolP(flagSet, name, shorthand, nil, usage)
   101  			return newMapValue(val, protoreflect.ValueOfBool)
   102  		}
   103  	case protoreflect.Uint64Kind:
   104  		switch valueKind {
   105  		case protoreflect.StringKind:
   106  			val := maps.Uint64ToStringP(flagSet, name, shorthand, nil, usage)
   107  			return newMapValue(val, protoreflect.ValueOfString)
   108  		case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
   109  			val := maps.Uint64ToInt32P(flagSet, name, shorthand, nil, usage)
   110  			return newMapValue(val, protoreflect.ValueOfInt32)
   111  		case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
   112  			val := maps.Uint64ToInt64P(flagSet, name, shorthand, nil, usage)
   113  			return newMapValue(val, protoreflect.ValueOfInt64)
   114  		case protoreflect.Uint32Kind:
   115  			val := maps.Uint64ToUint32P(flagSet, name, shorthand, nil, usage)
   116  			return newMapValue(val, protoreflect.ValueOfUint32)
   117  		case protoreflect.Uint64Kind:
   118  			val := maps.Uint64ToUint64P(flagSet, name, shorthand, nil, usage)
   119  			return newMapValue(val, protoreflect.ValueOfUint64)
   120  		case protoreflect.BoolKind:
   121  			val := maps.Uint64ToBoolP(flagSet, name, shorthand, nil, usage)
   122  			return newMapValue(val, protoreflect.ValueOfBool)
   123  		}
   124  	case protoreflect.BoolKind:
   125  		switch valueKind {
   126  		case protoreflect.StringKind:
   127  			val := maps.BoolToStringP(flagSet, name, shorthand, nil, usage)
   128  			return newMapValue(val, protoreflect.ValueOfString)
   129  		case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
   130  			val := maps.BoolToInt32P(flagSet, name, shorthand, nil, usage)
   131  			return newMapValue(val, protoreflect.ValueOfInt32)
   132  		case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
   133  			val := maps.BoolToInt64P(flagSet, name, shorthand, nil, usage)
   134  			return newMapValue(val, protoreflect.ValueOfInt64)
   135  		case protoreflect.Uint32Kind:
   136  			val := maps.BoolToUint32P(flagSet, name, shorthand, nil, usage)
   137  			return newMapValue(val, protoreflect.ValueOfUint32)
   138  		case protoreflect.Uint64Kind:
   139  			val := maps.BoolToUint64P(flagSet, name, shorthand, nil, usage)
   140  			return newMapValue(val, protoreflect.ValueOfUint64)
   141  		case protoreflect.BoolKind:
   142  			val := maps.BoolToBoolP(flagSet, name, shorthand, nil, usage)
   143  			return newMapValue(val, protoreflect.ValueOfBool)
   144  		}
   145  
   146  	}
   147  	return nil
   148  }
   149  
   150  type mapValue[K comparable, V any] struct {
   151  	value               *map[K]V
   152  	toProtoreflectValue func(V) protoreflect.Value
   153  }
   154  
   155  func newMapValue[K comparable, V any](mapV *map[K]V, toProtoreflectValue func(V) protoreflect.Value) mapValue[K, V] {
   156  	return mapValue[K, V]{value: mapV, toProtoreflectValue: toProtoreflectValue}
   157  }
   158  
   159  func (v mapValue[K, V]) Get(mutable protoreflect.Value) (protoreflect.Value, error) {
   160  	protoMap := mutable.Map()
   161  	for k, val := range *v.value {
   162  		protoMap.Set(protoreflect.MapKey(protoreflect.ValueOf(k)), v.toProtoreflectValue(val))
   163  	}
   164  	return mutable, nil
   165  }
   166  
   167  // keyValueResolver is a function that converts a string to a key that is primitive Type T
   168  type keyValueResolver[T comparable] func(string) (T, error)
   169  
   170  // compositeMapType is a map type that is composed of a key and value type that are both primitive types
   171  type compositeMapType[T comparable] struct {
   172  	keyValueResolver keyValueResolver[T]
   173  	keyType          string
   174  	valueType        Type
   175  }
   176  
   177  // compositeMapValue is a map value that is composed of a key and value type that are both primitive types
   178  type compositeMapValue[T comparable] struct {
   179  	keyValueResolver keyValueResolver[T]
   180  	keyType          string
   181  	valueType        Type
   182  	values           map[T]protoreflect.Value
   183  	ctx              context.Context
   184  	opts             *Builder
   185  }
   186  
   187  func (m compositeMapType[T]) DefaultValue() string {
   188  	return ""
   189  }
   190  
   191  func (m compositeMapType[T]) NewValue(ctx context.Context, opts *Builder) Value {
   192  	return &compositeMapValue[T]{
   193  		keyValueResolver: m.keyValueResolver,
   194  		valueType:        m.valueType,
   195  		keyType:          m.keyType,
   196  		ctx:              ctx,
   197  		opts:             opts,
   198  		values:           nil,
   199  	}
   200  }
   201  
   202  func (m *compositeMapValue[T]) Set(s string) error {
   203  	comaArgs := strings.Split(s, ",")
   204  	for _, arg := range comaArgs {
   205  		parts := strings.SplitN(arg, "=", 2)
   206  		if len(parts) != 2 {
   207  			return errors.New("invalid format, expected key=value")
   208  		}
   209  		key, val := parts[0], parts[1]
   210  
   211  		keyValue, err := m.keyValueResolver(key)
   212  		if err != nil {
   213  			return err
   214  		}
   215  
   216  		simpleVal := m.valueType.NewValue(m.ctx, m.opts)
   217  		err = simpleVal.Set(val)
   218  		if err != nil {
   219  			return err
   220  		}
   221  		protoValue, err := simpleVal.Get(protoreflect.Value{})
   222  		if err != nil {
   223  			return err
   224  		}
   225  		if m.values == nil {
   226  			m.values = make(map[T]protoreflect.Value)
   227  		}
   228  
   229  		m.values[keyValue] = protoValue
   230  	}
   231  
   232  	return nil
   233  }
   234  
   235  func (m *compositeMapValue[T]) Get(mutable protoreflect.Value) (protoreflect.Value, error) {
   236  	protoMap := mutable.Map()
   237  	for key, value := range m.values {
   238  		keyVal := protoreflect.ValueOf(key)
   239  		protoMap.Set(keyVal.MapKey(), value)
   240  	}
   241  	return protoreflect.ValueOfMap(protoMap), nil
   242  }
   243  
   244  func (m *compositeMapValue[T]) String() string {
   245  	if m.values == nil {
   246  		return ""
   247  	}
   248  
   249  	return fmt.Sprintf("%+v", m.values)
   250  }
   251  
   252  func (m *compositeMapValue[T]) Type() string {
   253  	return fmt.Sprintf("map[%s]%s", m.keyType, m.valueType.NewValue(m.ctx, m.opts).Type())
   254  }