knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/configmap/parser/parse.go (about) 1 /* 2 Copyright 2025 The Knative Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package parser 18 19 import ( 20 "fmt" 21 "strconv" 22 "strings" 23 "time" 24 ) 25 26 // ParseFunc is a function taking ConfigMap data and applying a parse operation to it. 27 type ParseFunc func(map[string]string) error 28 29 func Parse(data map[string]string, parsers ...ParseFunc) error { 30 for _, parse := range parsers { 31 if err := parse(data); err != nil { 32 return err 33 } 34 } 35 return nil 36 } 37 38 func AsFunc[T any]( 39 key string, 40 target *T, 41 parseVal func(s string) (T, error), 42 ) ParseFunc { 43 return func(data map[string]string) error { 44 if raw, ok := data[key]; ok { 45 val, err := parseVal(raw) 46 if err != nil { 47 return fmt.Errorf("failed to parse %q: %w", key, err) 48 } 49 *target = val 50 } 51 return nil 52 } 53 } 54 55 func As[T parseable](key string, target *T) ParseFunc { 56 return AsFunc(key, target, parse) 57 } 58 59 type parseable interface { 60 int | int16 | int32 | int64 | 61 uint | uint16 | uint32 | uint64 | 62 string | bool | float64 | float32 | 63 time.Duration 64 } 65 66 //nolint:gosec // ignore integer overflow 67 func parse[T parseable](s string) (T, error) { 68 var zero T 69 70 var val any 71 var err error 72 73 switch any(zero).(type) { 74 case string: 75 val = strings.TrimSpace(s) 76 case int16: 77 val, err = strconv.ParseInt(s, 10, 16) 78 val = int16(val.(int64)) 79 case int32: 80 val, err = strconv.ParseInt(s, 10, 32) 81 val = int32(val.(int64)) 82 case int64: 83 val, err = strconv.ParseInt(s, 10, 64) 84 case uint16: 85 val, err = strconv.ParseUint(s, 10, 16) 86 val = uint16(val.(uint64)) 87 case uint32: 88 val, err = strconv.ParseUint(s, 10, 32) 89 val = uint32(val.(uint64)) 90 case uint64: 91 val, err = strconv.ParseUint(s, 10, 64) 92 case float64: 93 val, err = strconv.ParseFloat(s, 64) 94 case float32: 95 val, err = strconv.ParseFloat(s, 64) 96 val = float32(val.(float64)) 97 case bool: 98 val, err = strconv.ParseBool(s) 99 case time.Duration: 100 val, err = time.ParseDuration(s) 101 case int: 102 val, err = strconv.ParseInt(s, 10, 0) 103 val = int(val.(int64)) 104 case uint: 105 val, err = strconv.ParseUint(s, 10, 0) 106 val = uint(val.(uint64)) 107 } 108 109 return val.(T), err 110 }