blasphem/pkg/config/config.go

83 lines
1.6 KiB
Go
Raw Normal View History

2022-09-25 11:42:36 -04:00
package config
import (
"errors"
"fmt"
"reflect"
"strings"
server "dynatron.me/x/blasphem/pkg/server/config"
"gopkg.in/yaml.v3"
)
2022-12-19 19:24:01 -05:00
type Configured interface {
Conf() *Config
}
2022-09-25 11:42:36 -04:00
type Config struct {
2022-10-02 14:39:55 -04:00
DataDir *string `yaml:"data_dir,omitempty"`
Server *server.Config `yaml:"server"`
2022-09-25 11:42:36 -04:00
}
const (
2022-09-26 15:00:21 -04:00
IncludeTag = "!include"
IncludeDirNamedTag = "!include_dir_named"
IncludeDirListTag = "!include_dir_list"
2022-09-25 11:42:36 -04:00
IncludeDirMergeNamedTag = "!include_dir_merge_named"
2022-09-26 15:00:21 -04:00
SecretTag = "!secret"
2022-09-25 11:42:36 -04:00
)
func (c *Config) UnmarshalYAML(y *yaml.Node) error {
if y.Kind != yaml.MappingNode {
return yerr(y, errors.New("config root must be a map"))
}
cV := reflect.ValueOf(c).Elem()
components := make(map[string]reflect.Value, cV.NumField())
for i := 0; i < cV.NumField(); i++ {
if tag, ok := cV.Type().Field(i).Tag.Lookup("yaml"); ok {
tags := strings.Split(tag, ",")
components[tags[0]] = cV.Field(i)
}
}
for i := 0; i < len(y.Content); i += 2 {
k, v := y.Content[i], y.Content[i+1]
2022-09-26 15:00:21 -04:00
switch v.LongTag() {
2022-09-25 11:42:36 -04:00
case IncludeTag:
fallthrough
case IncludeDirNamedTag:
fallthrough
case IncludeDirMergeNamedTag:
fallthrough
case SecretTag:
panic(fmt.Errorf("tag %s not implemented", v.LongTag()))
default:
var key string
err := k.Decode(&key)
if err != nil {
return yerr(y, err)
}
if comp, ok := components[key]; ok {
val := reflect.New(comp.Type())
err := v.Decode(val.Interface())
if err != nil {
return yerr(y, err)
}
comp.Set(val.Elem())
}
}
}
return nil
}
func yerr(y *yaml.Node, ye error) error {
return fmt.Errorf("line %d: %w", y.Line, ye)
}