-
Notifications
You must be signed in to change notification settings - Fork 0
/
extraction.go
122 lines (104 loc) · 2.82 KB
/
extraction.go
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package strongParser
import (
"os"
"reflect"
"strconv"
"strings"
)
// extractFieldValue
func extractFieldValue[T comparable](
parser *ConfigParser,
myType reflect.Type,
currentIndex int, section string,
converter fieldValueConverter[T]) T {
var realDefault T
var resultValue T
fByName := myType.Field(currentIndex)
if section == "" {
section = fByName.Tag.Get("section")
}
if section == "" && parser.options.MainSectionName != "" {
section = parser.options.MainSectionName
}
key := fByName.Tag.Get("key")
if key == "" {
// convert the field name to snake case
key = toSnakeCase(fByName.Name)
}
fType := strings.ToLower(fByName.Tag.Get("type"))
theValue, err := parser.Get(section, key)
if err == nil {
// first try: from config file.
resultValue, err = converter(fType, theValue)
if err == nil && resultValue != realDefault {
return resultValue
}
}
envTag := fByName.Tag.Get("env")
var envTries []string
if envTag == "" && parser.options.ReadEnv {
// if there is no env tag and we are told to allow
// reading values from env, try to read it from env.
if section != "" {
envTries = append(envTries, strings.ToUpper(section)+"_"+strings.ToUpper(key))
}
envTries = append(envTries, key)
envTries = append(envTries, strings.ToUpper(key))
} else {
// if we are given an env tag, just use that, instead of trying a few times
// to find the correct variable in env...
envTries = append(envTries, envTag)
}
for _, envTry := range envTries {
envValue := os.Getenv(envTry)
if envValue != "" {
resultValue, err = converter(fType, envValue)
if err == nil && resultValue != realDefault {
return resultValue
}
}
}
resultValue, _ = converter(fType, fByName.Tag.Get("default"))
return resultValue
}
func toSnakeCase(s string) string {
var result []rune
for i, c := range s {
if i > 0 && c >= 'A' && c <= 'Z' {
result = append(result, '_')
}
// lower-case the c and append
result = append(result, c|0x20)
}
return string(result)
}
func extractStr(fType, s string) (string, error) { return s, nil }
func parseAsRune(value string) rune {
if value == "" {
return 0
}
return ([]rune(value))[0]
}
func extractInt64(fType, strValue string) (int64, error) {
switch fType {
default:
// consider int64 for default
fallthrough
case "int64":
return strconv.ParseInt(strValue, 10, 64)
case "rune":
return int64(parseAsRune(strValue)), nil
}
}
func extractUInt64(_, strValue string) (uint64, error) {
return strconv.ParseUint(strValue, 10, 64)
}
func extractBool(fType, strValue string) (bool, error) {
return BoolMapping[strings.ToLower(strValue)], nil
}
func extractFloat64(fType, strValue string) (float64, error) {
return strconv.ParseFloat(strValue, 64)
}
func extractComplex128(fType, strValue string) (complex128, error) {
return strconv.ParseComplex(strValue, 128)
}