aicra/checker/public.go

97 lines
2.0 KiB
Go

package checker
import (
"fmt"
"plugin"
"strings"
)
// CreateRegistry creates an empty type registry
// if TRUE is given, it will use default Types
// see ./default/ folder
func CreateRegistry(useDefaultTypes bool) *TypeRegistry {
return &TypeRegistry{
Types: make([]Type, 0),
}
}
// Add adds a type to the registry; it must be a
// valid and existing plugin name without the .so extension
func (tr *TypeRegistry) Add(pluginName string) error {
/* (1) Check plugin name */
if len(pluginName) < 1 {
return fmt.Errorf("Plugin name must not be empty")
}
/* (2) Check plugin extension */
if strings.HasSuffix(pluginName, ".so") {
return fmt.Errorf("Plugin name must be provided without extension: '%s'", pluginName[0:len(pluginName)-3])
}
/* (3) Try to load the plugin */
p, err := plugin.Open(fmt.Sprintf("%s.so", pluginName))
if err != nil {
return err
}
/* (4) Export wanted properties */
matcher, err := p.Lookup("Match")
if err != nil {
return fmt.Errorf("Missing method 'Match()'; %s", err)
}
checker, err := p.Lookup("Check")
if err != nil {
return fmt.Errorf("Missing method 'Check()'; %s", err)
}
/* (5) Cast Match+Check */
matcherCast, ok := matcher.(func(string) bool)
if !ok {
return fmt.Errorf("Match() is malformed")
}
checkerCast, ok := checker.(func(interface{}) bool)
if !ok {
return fmt.Errorf("Check() is malformed")
}
/* (6) Add type to registry */
tr.Types = append(tr.Types, Type{
Match: matcherCast,
Check: checkerCast,
})
return nil
}
// Checks the 'value' which must be of type 'name'
func (tr TypeRegistry) Run(name string, value interface{}) error {
var T *Type = nil
/* (1) Iterate to find matching type (take first) */
for _, t := range tr.Types {
// stop if found
if t.Match(name) {
T = &t
break
}
}
/* (2) Abort if no matching type */
if T == nil {
return fmt.Errorf("No matching type")
}
/* (3) Check */
if !T.Check(value) {
return fmt.Errorf("Does not match")
}
return nil
}