github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/config/types.go (about) 1 package config 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 "strings" 8 ) 9 10 // Strings is a []string that mapstructure can deserialize from a single string or from a list 11 // of strings. 12 type Strings []string 13 14 var ( 15 ourStringsType = reflect.TypeOf(Strings{}) 16 stringType = reflect.TypeOf("") 17 stringSliceType = reflect.TypeOf([]string{}) 18 ) 19 20 // DecodeStrings is a mapstructure.HookFuncType that decodes a single string value or a slice 21 // of strings into Strings. 22 func DecodeStrings(fromValue reflect.Value, toValue reflect.Value) (interface{}, error) { 23 if toValue.Type() != ourStringsType { 24 return fromValue.Interface(), nil 25 } 26 if fromValue.Type() == stringSliceType { 27 return Strings(fromValue.Interface().([]string)), nil 28 } 29 if fromValue.Type() == stringType { 30 return Strings(strings.Split(fromValue.String(), ",")), nil 31 } 32 return fromValue.Interface(), nil 33 } 34 35 type SecureString string 36 37 // String returns an elided version. It is safe to call for logging. 38 func (SecureString) String() string { 39 return "[SECRET]" 40 } 41 42 // SecureValue returns the actual value of s as a string. 43 func (s SecureString) SecureValue() string { 44 return string(s) 45 } 46 47 // OnlyString is a string that can deserialize only from a string. Use it 48 // to prevent YAML configuration reading a number-like string with leading 49 // zeros, and then Viper using mapstructure to convert it silently back to a 50 // string and losing the leading zeros. 51 type OnlyString string 52 53 var ( 54 onlyStringType = reflect.TypeOf(OnlyString("")) 55 ErrMustBeString = errors.New("must be a string") 56 ) 57 58 func (o OnlyString) String() string { 59 return string(o) 60 } 61 62 // DecodeOnlyString is a mapstructure.HookFuncType that decodes a string 63 // value as an OnlyString, but fails on all other values. It is useful to 64 // force parsing of a field that can contain just digits as a string, when 65 // the leading digit might be 0. 66 func DecodeOnlyString(fromValue reflect.Value, toValue reflect.Value) (interface{}, error) { 67 if toValue.Type() != onlyStringType { 68 // Not trying to translate to OnlyString 69 return fromValue.Interface(), nil 70 } 71 if fromValue.Type() != stringType { 72 return nil, fmt.Errorf("%w, not a %s", ErrMustBeString, fromValue.Type().String()) 73 } 74 return OnlyString(fromValue.Interface().(string)), nil 75 }