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 }