mirror of
https://github.com/jlelse/GoBlog
synced 2024-06-16 14:15:00 +00:00
81 lines
1.9 KiB
Go
81 lines
1.9 KiB
Go
|
package plugins
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
|
||
|
"github.com/traefik/yaegi/interp"
|
||
|
)
|
||
|
|
||
|
// NewPluginHost initializes a PluginHost.
|
||
|
func NewPluginHost(symbols interp.Exports) *PluginHost {
|
||
|
return &PluginHost{
|
||
|
Plugins: []*plugin{},
|
||
|
PluginTypes: map[string]reflect.Type{},
|
||
|
Symbols: symbols,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// AddPluginType adds a plugin type to the list.
|
||
|
// The interface for the pluginType parameter should be a nil of the plugin type interface:
|
||
|
//
|
||
|
// (*PluginInterface)(nil)
|
||
|
func (h *PluginHost) AddPluginType(name string, pluginType interface{}) {
|
||
|
h.PluginTypes[name] = reflect.TypeOf(pluginType).Elem()
|
||
|
}
|
||
|
|
||
|
// LoadPlugin loads a new plugin to the host.
|
||
|
func (h *PluginHost) LoadPlugin(config *PluginConfig) (any, error) {
|
||
|
p := &plugin{
|
||
|
Config: config,
|
||
|
}
|
||
|
err := p.initPlugin(h)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
err = h.validatePlugin(p)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
h.Plugins = append(h.Plugins, p)
|
||
|
return p.plugin.Interface(), nil
|
||
|
}
|
||
|
|
||
|
func (h *PluginHost) validatePlugin(p *plugin) error {
|
||
|
pType := reflect.TypeOf(p.plugin.Interface())
|
||
|
|
||
|
if _, ok := h.PluginTypes[p.Config.PluginType]; !ok {
|
||
|
return fmt.Errorf("validatePlugin: %v: %w", p.Config.PluginType, ErrInvalidType)
|
||
|
}
|
||
|
|
||
|
if !pType.Implements(h.PluginTypes[p.Config.PluginType]) {
|
||
|
return fmt.Errorf("validatePlugin:%v: %w %v", p, ErrValidatingPlugin, p.Config.PluginType)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// GetPlugins returns a list of all plugins.
|
||
|
func (h *PluginHost) GetPlugins() (list []any) {
|
||
|
for _, p := range h.Plugins {
|
||
|
list = append(list, p.plugin.Interface())
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// GetPluginsForType returns all the plugins that are of type pluginType or empty if the pluginType doesn't exist.
|
||
|
func GetPluginsForType[T any](h *PluginHost, pluginType string) (list []T) {
|
||
|
if _, ok := h.PluginTypes[pluginType]; !ok {
|
||
|
return
|
||
|
}
|
||
|
for _, p := range h.Plugins {
|
||
|
if p.Config.PluginType != pluginType {
|
||
|
continue
|
||
|
}
|
||
|
if t, ok := p.plugin.Interface().(T); ok {
|
||
|
list = append(list, t)
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|