Files
engine/config/config.go
2022-02-11 15:21:29 +08:00

162 lines
3.1 KiB
Go

package config
import (
"net"
"net/http"
"reflect"
"strings"
"time"
)
type Config map[string]any
type Second int
func (s Second) Duration() time.Duration {
return time.Duration(s) * time.Second
}
type Plugin interface {
Update(Config)
}
type TCPPlugin interface {
Plugin
ServeTCP(*net.TCPConn)
}
type HTTPPlugin interface {
Plugin
http.Handler
}
func (config Config) Unmarshal(s any) {
if s == nil {
return
}
var el reflect.Value
if v, ok := s.(reflect.Value); ok {
el = v
} else {
el = reflect.ValueOf(s)
}
if el.Kind() == reflect.Pointer {
el = el.Elem()
}
t := el.Type()
if t.Kind() == reflect.Map {
for k, v := range config {
el.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v).Convert(t.Elem()))
}
return
}
//字段映射,小写对应的大写
nameMap := make(map[string]string)
for i, j := 0, t.NumField(); i < j; i++ {
name := t.Field(i).Name
nameMap[strings.ToLower(name)] = name
}
for k, v := range config {
// 需要被写入的字段
fv := el.FieldByName(nameMap[k])
if value := reflect.ValueOf(v); value.Kind() == reflect.Slice {
l := value.Len()
s := reflect.MakeSlice(fv.Type(), l, value.Cap())
for i := 0; i < l; i++ {
fv := value.Field(i)
if fv.Type() == reflect.TypeOf(config) {
fv.FieldByName("Unmarshal").Call([]reflect.Value{s.Field(i)})
} else {
s.Field(i).Set(fv)
}
}
fv.Set(s)
} else if child, ok := v.(Config); ok {
if fv.Kind() == reflect.Map {
if fv.IsNil() {
fv.Set(reflect.MakeMap(fv.Type()))
}
}
child.Unmarshal(fv)
} else {
fv.Set(value)
}
}
}
// 覆盖配置
func (config Config) Assign(source Config) {
for k, v := range source {
switch m := config[k].(type) {
case Config:
m.Assign(v.(Config))
default:
config[k] = v
}
}
}
// 合并配置,不覆盖
func (config Config) Merge(source Config) {
for k, v := range source {
if _, ok := config[k]; !ok {
switch m := config[k].(type) {
case Config:
m.Merge(v.(Config))
default:
config[k] = v
}
}
}
}
func (config Config) Set(key string, value any) {
config[strings.ToLower(key)] = value
}
func (config Config) Has(key string) (ok bool) {
_, ok = config[strings.ToLower(key)]
return
}
func (config Config) HasChild(key string) (ok bool) {
_, ok = config[strings.ToLower(key)].(Config)
return ok
}
func (config Config) GetChild(key string) Config {
if v, ok := config[strings.ToLower(key)]; ok {
return v.(Config)
}
return nil
}
func Struct2Config(s any) (config Config) {
config = make(Config)
var t reflect.Type
var v reflect.Value
if vv, ok := s.(reflect.Value); ok {
v = vv
t = vv.Type()
} else {
t = reflect.TypeOf(s)
v = reflect.ValueOf(s)
if t.Kind() == reflect.Pointer {
v = v.Elem()
t = t.Elem()
}
}
for i, j := 0, t.NumField(); i < j; i++ {
ft := t.Field(i)
switch ft.Type.Kind() {
case reflect.Struct:
config[ft.Name] = Struct2Config(v.Field(i))
case reflect.Slice:
fallthrough
default:
reflect.ValueOf(config).SetMapIndex(reflect.ValueOf(strings.ToLower(ft.Name)), v.Field(i))
}
}
return
}