mirror of
https://github.com/xaionaro-go/streamctl.git
synced 2025-09-27 03:45:52 +08:00
150 lines
3.2 KiB
Go
150 lines
3.2 KiB
Go
package streamcontrol
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/goccy/go-yaml"
|
|
"github.com/hashicorp/go-multierror"
|
|
)
|
|
|
|
type platformMeta struct {
|
|
PlatformSpecificConfig reflect.Type
|
|
StreamProfile reflect.Type
|
|
Config reflect.Type
|
|
}
|
|
|
|
var registry = map[PlatformName]platformMeta{}
|
|
|
|
func RegisterPlatform[PSC PlatformSpecificConfig, SP StreamProfile](id PlatformName) {
|
|
var (
|
|
platCfgSample PSC
|
|
profileSample SP
|
|
configSample PlatformConfig[PSC, SP]
|
|
)
|
|
|
|
if _, ok := registry[id]; ok {
|
|
panic(fmt.Errorf("platform '%s' is already registered", id))
|
|
}
|
|
|
|
registry[id] = platformMeta{
|
|
PlatformSpecificConfig: reflect.TypeOf(platCfgSample),
|
|
StreamProfile: reflect.TypeOf(profileSample),
|
|
Config: reflect.TypeOf(configSample),
|
|
}
|
|
}
|
|
|
|
func IsInitialized(
|
|
cfg Config,
|
|
platID PlatformName,
|
|
) bool {
|
|
err := ConvertPlatformConfigInplace(cfg, platID)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
platCfg := cfg[platID]
|
|
if platCfg == nil {
|
|
return false
|
|
}
|
|
return platCfg.IsInitialized()
|
|
}
|
|
|
|
func ConvertPlatformConfigInplace(
|
|
cfg Config,
|
|
platID PlatformName,
|
|
) error {
|
|
platCfg := cfg[platID]
|
|
if platCfg == nil {
|
|
return nil
|
|
}
|
|
|
|
var err error
|
|
platCfg.Config, err = GetAbstractPlatformSpecificConfig(cfg, platID)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to convert the platform specific part of the config: %w", err)
|
|
}
|
|
|
|
err = ConvertAbstractStreamProfiles(platCfg.StreamProfiles, platID)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to convert the stream profiles of the config: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func GetAbstractPlatformSpecificConfig(
|
|
cfg Config,
|
|
platID PlatformName,
|
|
) (PlatformSpecificConfig, error) {
|
|
meta := registry[platID]
|
|
platCfgCfgTyped := reflect.New(meta.PlatformSpecificConfig).Interface().(PlatformSpecificConfig)
|
|
|
|
platCfg := cfg[platID]
|
|
if platCfg == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
var b []byte
|
|
switch platCfgCfg := platCfg.Config.(type) {
|
|
case nil:
|
|
return nil, nil
|
|
case RawMessage:
|
|
b = platCfgCfg
|
|
case *RawMessage:
|
|
b = *platCfgCfg
|
|
case PlatformSpecificConfig:
|
|
return platCfgCfg, nil
|
|
default:
|
|
return nil, fmt.Errorf("unable to get the config: expected type '%T' or RawMessage, but received type '%T'", platCfgCfgTyped, platCfgCfg)
|
|
}
|
|
|
|
err := yaml.Unmarshal(b, platCfgCfgTyped)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return platCfgCfgTyped, nil
|
|
}
|
|
|
|
func ConvertAbstractStreamProfiles(
|
|
s StreamProfiles[AbstractStreamProfile],
|
|
platID PlatformName,
|
|
) error {
|
|
var err *multierror.Error
|
|
for k, v := range s {
|
|
var err error
|
|
s[k], err = ConvertStreamProfile(v, platID)
|
|
err = multierror.Append(err, err)
|
|
}
|
|
return err.ErrorOrNil()
|
|
}
|
|
|
|
func ConvertStreamProfile(
|
|
p StreamProfile,
|
|
platID PlatformName,
|
|
) (StreamProfile, error) {
|
|
meta := registry[platID]
|
|
streamProfileTyped := reflect.New(meta.StreamProfile).Interface().(StreamProfile)
|
|
|
|
var b []byte
|
|
switch p := p.(type) {
|
|
case nil:
|
|
return nil, nil
|
|
case RawMessage:
|
|
b = p
|
|
case *RawMessage:
|
|
b = *p
|
|
case AbstractStreamProfile:
|
|
return p, nil
|
|
default:
|
|
return nil, fmt.Errorf("unable to get the config: expected type '%T' or RawMessage, but received type '%T'", streamProfileTyped, p)
|
|
}
|
|
|
|
err := yaml.Unmarshal(b, streamProfileTyped)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return streamProfileTyped, nil
|
|
}
|