package registry import ( "path" "reflect" "runtime" ) // Global var ( Global = New() Register = Global.Register Descriptions = Global.Descriptions GetEntry = Global.Entry Add = Global.Add ) // M Alias for map[string]interface{} type M = map[string]interface{} // R the function registry type R struct { data map[string]*Entry } // New creates a new registry func New() *R { r := &R{map[string]*Entry{}} // create a base function here? return r } // Clone an existing registry func (r *R) Clone() *R { newR := &R{map[string]*Entry{}} for k, v := range r.data { newR.data[k] = v } return newR } // Add unnamed function func (r *R) Add(fns ...interface{}) EDescriber { b := EDescriber{} for _, fn := range fns { if reflect.TypeOf(fn).Kind() != reflect.Func { return nil } // Automatic naming name := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() name = path.Ext(name)[1:] b = append(b, r.Register(name, fn)) } return b } //Register should be a func only register func (r *R) Register(name string, v interface{}) *Entry { e := NewEntry(r, v) if e.err != nil { return e } r.data[name] = e return e } // Get an entry func (r *R) Get(name string, params ...interface{}) (interface{}, error) { e, ok := r.data[name] if !ok { return nil, ErrNotFound } v := e.fn // We already know this is a function // and that returns 1 or more values vtyp := reflect.TypeOf(v) if vtyp.Out(0).Kind() != reflect.Func { return v, nil } // Constructor fparam := make([]reflect.Value, len(params)) for i := range params { fparam[i] = reflect.ValueOf(params[i]) } // Call the func and return the thing v = reflect.ValueOf(v).Call(fparam)[0].Interface() return v, nil } // Entry fetches entries from the register func (r *R) Entry(name string) (*Entry, error) { e, ok := r.data[name] if !ok { return nil, ErrNotFound } return e, nil } //Describe named fn // Descriptions Description list func (r *R) Descriptions() (map[string]Description, error) { ret := map[string]Description{} for k, e := range r.data { ret[k] = *e.Description } return ret, nil }