82 lines
1.6 KiB
Go
82 lines
1.6 KiB
Go
package config
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
|
|
server "dynatron.me/x/blasphem/pkg/server/config"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type Configured interface {
|
|
Conf() *Config
|
|
}
|
|
|
|
type Config struct {
|
|
DataDir *string `yaml:"data_dir,omitempty"`
|
|
Server *server.Config `yaml:"server"`
|
|
}
|
|
|
|
const (
|
|
IncludeTag = "!include"
|
|
IncludeDirNamedTag = "!include_dir_named"
|
|
IncludeDirListTag = "!include_dir_list"
|
|
IncludeDirMergeNamedTag = "!include_dir_merge_named"
|
|
SecretTag = "!secret"
|
|
)
|
|
|
|
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]
|
|
|
|
switch v.LongTag() {
|
|
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)
|
|
}
|