Files
streamctl/pkg/streamcontrol/registry.go
2024-10-22 20:55:24 +01:00

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
}