kde-lockscreen-suspend-display/config/config.go

115 lines
2.4 KiB
Go

package config
import (
"os"
"strings"
"fmt"
"reflect"
"errors"
"strconv"
)
var ConfigFetchMethod = os.Environ
func Build(prefix string, configStruct interface{}) (err error) {
defer func() {
if e := recover(); e != nil {
switch r := e.(type) {
case string:
err = errors.New(r)
case error:
err = r
default:
err = errors.New("Undefined panic")
}
}
}()
assertIsPtr(configStruct)
fieldNames := getConfigStructFieldNames(configStruct)
config := loadConfig(prefix)
structRef := reflect.ValueOf(configStruct)
for _, fieldName := range fieldNames {
value, ok := config[fieldName]
if !ok {
// no such field loaded, avoid overwriting default
continue
}
field := reflect.Indirect(structRef).FieldByName(fieldName)
typeRef := field.Type()
ret, err := tryParseString(value, typeRef.Kind())
if err != nil {
return err
}
field.Set(reflect.ValueOf(ret).Convert(typeRef))
}
return nil
}
func tryParseString(what string, toType reflect.Kind) (interface{}, error) {
switch toType {
case reflect.String:
return what, nil
case reflect.Int:
i, err := strconv.Atoi(what)
if err != nil {
return nil, err
}
return i, nil
case reflect.Bool:
b, err := strconv.ParseBool(what)
if err != nil {
return nil, err
}
return b, nil
default:
return nil, fmt.Errorf("Failed to parse value %v", what)
}
}
func assertIsPtr(what interface{}) {
r := reflect.ValueOf(what)
if r.Kind() != reflect.Ptr {
panic(fmt.Errorf("Supplied value is not a pointer to a struct"))
}
}
func getConfigStructFieldNames(configStruct interface{}) []string {
configFields := []string{}
val := reflect.ValueOf(configStruct).Elem()
for i := 0; i < val.NumField(); i++ {
configFields = append(configFields, val.Type().Field(i).Name)
}
return configFields
}
func loadConfig(prefix string) map[string]string {
prefix = fmt.Sprintf("%s_", prefix)
config := map[string]string{}
for _, env := range ConfigFetchMethod() {
parts := strings.SplitN(env, "=", 2)
key, value := parts[0], parts[1]
if strings.HasPrefix(key, prefix) {
key = strings.TrimPrefix(key, prefix)
config[key] = value
}
}
return config
}
// CheckKeysExist returns an error if not all keys are present in config map
func CheckKeysExist(config map[string]string, keys ...string) error {
for _, key := range keys {
if _, ok := config[key]; ok {
return fmt.Errorf("Config key '%s' is not set", key)
}
}
return nil
}