Files
engine/config/config.go
dexter 5b51e8c494 1.修复读取ts中aac格式数据多次flush问题
2.修复subscribe结束时判断IsClosed调用对象错误
3.增加DefaultYaml功能
2023-01-03 18:55:32 +08:00

235 lines
5.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package config
import (
"net"
"net/http"
"reflect"
"strings"
"m7s.live/engine/v4/log"
)
type Config map[string]any
type Plugin interface {
// 可能的入参类型FirstConfig 第一次初始化配置Config 后续配置更新SE系列StateEvent流状态变化事件
OnEvent(any)
}
type TCPPlugin interface {
Plugin
ServeTCP(*net.TCPConn)
}
type HTTPPlugin interface {
Plugin
http.Handler
}
// CreateElem 创建Map或者Slice中的元素
func (config Config) CreateElem(eleType reflect.Type) reflect.Value {
if eleType.Kind() == reflect.Pointer {
newv := reflect.New(eleType.Elem())
config.Unmarshal(newv)
return newv
} else {
newv := reflect.New(eleType)
config.Unmarshal(newv)
return newv.Elem()
}
}
func (config Config) Unmarshal(s any) {
defer func() {
if err := recover(); err != nil {
log.Error("Unmarshal error:", err)
}
}()
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 {
tt := t.Elem()
for k, v := range config {
if child, ok := v.(Config); ok {
//复杂类型
el.SetMapIndex(reflect.ValueOf(k), child.CreateElem(tt))
} else {
//基本类型
el.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v).Convert(tt))
}
}
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 {
name, ok := nameMap[k]
if !ok {
log.Error("no config named:", k)
continue
}
// 需要被写入的字段
fv := el.FieldByName(name)
fvKind := fv.Kind()
ft := fv.Type()
value := reflect.ValueOf(v)
if child, ok := v.(Config); ok { //处理值是递归情况map)
if fvKind == reflect.Map {
if fv.IsNil() {
fv.Set(reflect.MakeMap(ft))
}
}
child.Unmarshal(fv)
} else {
switch fvKind {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
fv.SetUint(uint64(value.Int()))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
fv.SetInt(value.Int())
case reflect.Float32, reflect.Float64:
if value.CanFloat() {
fv.SetFloat(value.Float())
} else {
fv.SetFloat(float64(value.Int()))
}
case reflect.Slice:
var s reflect.Value
if value.Kind() == reflect.Slice {
l := value.Len()
s = reflect.MakeSlice(ft, l, value.Cap())
for i := 0; i < l; i++ {
fv := value.Index(i)
item := s.Index(i)
if child, ok := fv.Interface().(Config); ok {
item.Set(child.CreateElem(ft.Elem()))
} else if fv.Kind() == reflect.Interface {
item.Set(reflect.ValueOf(fv.Interface()).Convert(item.Type()))
} else {
item.Set(fv)
}
}
} else {
//值是单值,但类型是数组,默认解析为一个元素的数组
s = reflect.MakeSlice(ft, 1, 1)
s.Index(0).Set(value)
}
fv.Set(s)
default:
fv.Set(value)
}
}
}
}
// 覆盖配置
func (config Config) Assign(source Config) {
for k, v := range source {
switch m := config[k].(type) {
case Config:
switch vv := v.(type) {
case Config:
m.Assign(vv)
case map[string]any:
m.Assign(Config(vv))
}
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:
log.Debug("merge", k, v)
config[k] = v
}
} else {
log.Debug("exist", k)
}
}
}
func (config *Config) Set(key string, value any) {
if *config == nil {
*config = Config{strings.ToLower(key): value}
} else {
(*config)[strings.ToLower(key)] = value
}
}
func (config Config) Get(key string) any {
v, _ := config[strings.ToLower(key)]
return v
}
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 && v != nil {
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)
if !ft.IsExported() {
continue
}
name := strings.ToLower(ft.Name)
switch ft.Type.Kind() {
case reflect.Struct:
config[name] = Struct2Config(v.Field(i))
case reflect.Slice:
fallthrough
default:
reflect.ValueOf(config).SetMapIndex(reflect.ValueOf(name), v.Field(i))
}
}
return
}