// Validate ensures the Meta provides the necessary information needed // to be a valid pub meta. func (p Meta) Validate() error { if p.Name == "" { return errors.New("Empty Name") } if p.Desc == "" { return errors.New("Empty Description") } if p.Package == "" { return errors.New("Empty Package") } if p.Inject == nil { return errors.New("No Injector") } if !reflection.IsFuncType(p.Inject) { return errors.New("Inject is not a Function") } // Must have either zero or one argument for functions. if !reflection.HasArgumentSize(p.Inject, 0) && !reflection.HasArgumentSize(p.Inject, 1) { return errors.New("Argument Size Greater Than 1") } return nil }
// Q adds a new function type into the queue. func (m *MQue) Q(mx interface{}, rmx ...func()) End { if !reflection.IsFuncType(mx) { return nil } tm, _ := reflection.FuncValue(mx) var hasArgs bool var tu reflect.Type args, _ := reflection.GetFuncArgumentsType(mx) if size := len(args); size != 0 { tu = args[0] hasArgs = true } if !hasArgs { index := len(m.any.tms) m.any.tms = append(m.any.tms, tm) return &mqueSubIndex{ index: index, queue: m.any, ending: rmx, } } var sub *mqueSub { for _, tSub := range m.muxers { if tSub.CanRun(tu) { sub = tSub break } } } if sub != nil { tindex := len(sub.tms) sub.tms = append(sub.tms, tm) return &mqueSubIndex{ index: tindex, queue: sub, ending: rmx, } } var mq mqueSub mq.has = true mq.am = tu mq.tms = []reflect.Value{tm} m.muxers = append(m.muxers, &mq) return &mqueSubIndex{ index: 0, queue: &mq, ending: rmx, } }
// Wrap returns a new Handler wrapping the provided value as needed if // it matches its DataHandler, ErrorHandler, Handler or magic function type. // MagicFunction type is a function which follows this type form: // func(context.Context, error, <CustomType>). func Wrap(node interface{}) Handler { var hl Handler switch mh := node.(type) { case Handler: hl = node.(Handler) case func(): hl = func(ctx context.Context, err error, d interface{}) (interface{}, error) { node.(func())() if err != nil { return nil, err } return d, err } case func(context.Context, error, interface{}) (interface{}, error): hl = node.(func(context.Context, error, interface{}) (interface{}, error)) case func(context.Context, interface{}): hl = wrapDataWithNoReturn(node.(func(context.Context, interface{}))) case func(context.Context, interface{}) interface{}: hl = wrapDataWithReturn(node.(func(context.Context, interface{}) interface{})) case func(context.Context, interface{}) (interface{}, error): hl = wrapData(node.(func(context.Context, interface{}) (interface{}, error))) case func(context.Context, error) (interface{}, error): hl = wrapError(node.(func(context.Context, error) (interface{}, error))) case func(context.Context, error): hl = func(ctx context.Context, err error, d interface{}) (interface{}, error) { if err != nil { node.(func(context.Context, error))(ctx, err) } return d, err } case func(context.Context, error) error: hl = func(ctx context.Context, err error, d interface{}) (interface{}, error) { if err != nil { (node.(func(context.Context, error)))(ctx, err) } return d, err } case func(interface{}) (interface{}, error): hl = func(ctx context.Context, err error, d interface{}) (interface{}, error) { if err != nil { return nil, err } return mh(d) } case func(interface{}) interface{}: hl = wrapDataOnly(node.(func(interface{}) interface{})) case func(interface{}): hl = wrapJustData(node.(func(interface{}))) case func(error): hl = wrapJustError(node.(func(error))) case func(error) error: hl = wrapErrorReturn(node.(func(error) error)) case func() interface{}: hl = wrapNoData(node.(func() interface{})) case func(interface{}) error: hl = wrapErrorOnly(node.(func(interface{}) error)) default: if !reflection.IsFuncType(node) { return nil } tm, _ := reflection.FuncValue(node) args, _ := reflection.GetFuncArgumentsType(node) dLen := len(args) var data reflect.Type var dZero reflect.Value var useContext bool var useErr bool var useData bool var isCustom bool // Check if this first item is a context.Context type. if dLen < 2 { useContext, _ = reflection.CanSetForType(ctxType, args[0]) useErr, _ = reflection.CanSetForType(errorType, args[0]) if !useErr { data = args[0] dZero = reflect.Zero(data) useData = true isCustom = true } } if dLen == 2 { useContext, _ = reflection.CanSetForType(ctxType, args[0]) useErr, _ = reflection.CanSetForType(errorType, args[1]) if !useErr { data = args[1] dZero = reflect.Zero(data) useData = true isCustom = true } } if dLen > 2 { useContext, _ = reflection.CanSetForType(ctxType, args[0]) useErr, _ = reflection.CanSetForType(errorType, args[1]) data = args[2] dZero = reflect.Zero(data) useData = true if !useContext || !useData || !useErr { return nil } } if !useData && !useErr { return nil } hl = func(ctx context.Context, err error, val interface{}) (interface{}, error) { var fnArgs []reflect.Value var resArgs []reflect.Value var mctx reflect.Value me := dZeroError md := dZero if useContext { mctx = reflect.ValueOf(ctx) } if err != nil { me = reflect.ValueOf(err) } // Flag to skip function if data does not match. breakOfData := true if val != nil && useData { ok, convertData := reflection.CanSetForType(data, reflect.TypeOf(val)) if ok { breakOfData = false md = reflect.ValueOf(val) if convertData { md = md.Convert(data) } } } if !useContext && !useData && !useErr { resArgs = tm.Call(nil) } else { if isCustom && !useErr && err != nil { return nil, err } if !useContext && !useData && useErr && err != nil { return nil, err } if useContext && !useData && useErr && err != nil { return nil, err } // Call the function if it only cares about the error if useContext && useErr && me != dZeroError && !useData { fnArgs = []reflect.Value{mctx, me} } // If data does not match then skip this fall. if breakOfData && len(fnArgs) < 1 { return nil, ErrInvalidType } if !breakOfData { if useContext && useErr && useData { fnArgs = []reflect.Value{mctx, me, md} } if useContext && !useErr && useData { fnArgs = []reflect.Value{mctx, md} } if !useContext && useData && useErr { fnArgs = []reflect.Value{me, md} } if !useContext && useData && !useErr { fnArgs = []reflect.Value{md} } } resArgs = tm.Call(fnArgs) } resLen := len(resArgs) if resLen > 0 { if resLen < 2 { rOnly := resArgs[0] if erErr, ok := rOnly.Interface().(error); ok { return nil, erErr } return rOnly.Interface(), nil } rData := resArgs[0].Interface() rErr := resArgs[1].Interface() if erErr, ok := rErr.(error); ok { return rData, erErr } return rData, nil } return dZero, nil } } return hl }
// MagicApplier wraps the function type recieved applying any magic for the // expected types, returning a SubApplier to call the functions as needed. func MagicApplier(handle interface{}) SubApplier { switch handle.(type) { case func(context.Context, interface{}, interface{}) (interface{}, error): return handle.(func(context.Context, interface{}, interface{}) (interface{}, error)) case func(interface{}, interface{}) (interface{}, error): hl := handle.(func(interface{}, interface{}) (interface{}, error)) return func(_ context.Context, d1 interface{}, d2 interface{}) (interface{}, error) { return hl(d1, d2) } default: if !reflection.IsFuncType(handle) { return nil } tm, _ := reflection.FuncValue(handle) args, _ := reflection.GetFuncArgumentsType(handle) dLen := len(args) if dLen < 2 { return nil } var useContext bool var useOne bool var d1 reflect.Type var d2 reflect.Type var d1Zero reflect.Value var d2Zero reflect.Value if dLen == 2 { useContext, _ = reflection.CanSetForType(ctxType, args[0]) if useContext { d1 = args[1] d1Zero = reflect.Zero(d1) useOne = true } else { d1 = args[0] d1Zero = reflect.Zero(d1) d2 = args[1] d2Zero = reflect.Zero(d2) } } if dLen > 2 { useContext, _ = reflection.CanSetForType(ctxType, args[0]) if !useContext { return nil } d1 = args[0] d1Zero = reflect.Zero(d1) d2 = args[1] d2Zero = reflect.Zero(d2) } return func(ctx context.Context, dl interface{}, rl interface{}) (interface{}, error) { var fnArgs []reflect.Value var resArgs []reflect.Value if useContext { fnArgs = append(fnArgs, reflect.ValueOf(ctx)) } var dv1 reflect.Value var dv2 reflect.Value if dl != nil { dv1 = reflect.ValueOf(dl) } else { dv1 = d1Zero } if rl != nil { dv2 = reflect.ValueOf(rl) } else { dv2 = d2Zero } if !useOne { can, convert := reflection.CanSetFor(d1, dv1) if !can { return nil, ErrInvalidType } can2, convert2 := reflection.CanSetFor(d2, dv2) if !can2 { return nil, ErrInvalidType } if convert { dv1 = dv1.Convert(d1) } if convert2 { dv2 = dv2.Convert(d2) } fnArgs = append(fnArgs, dv1, dv2) resArgs = tm.Call(fnArgs) resLen := len(resArgs) // If it has no return, by logic, this is a secondary lift, hence // return the first argument. if resLen < 1 { return dl, nil } if resLen < 2 { rOnly := resArgs[0] if erErr, ok := rOnly.Interface().(error); ok { return nil, erErr } return rOnly.Interface(), nil } rData := resArgs[0].Interface() rErr := resArgs[1].Interface() if erErr, ok := rErr.(error); ok { return rData, erErr } return rData, nil } var useFirst bool can, convert := reflection.CanSetFor(d1, dv1) if can { useFirst = true if convert { dv1 = dv1.Convert(d1) } if useFirst { fnArgs = append(fnArgs, dv1) } } if !useFirst { can, convert = reflection.CanSetFor(d2, dv2) if !can { return nil, errors.New("Invalid Type Recieved") } if can && convert { dv2 = dv2.Convert(d2) } fnArgs = append(fnArgs, dv2) } resArgs = tm.Call(fnArgs) resLen := len(resArgs) // If it has no return, by logic, this is a secondary lift, hence // return the first argument. if resLen < 1 { return dl, nil } if resLen < 2 { rOnly := resArgs[0] if erErr, ok := rOnly.Interface().(error); ok { return nil, erErr } return rOnly.Interface(), nil } rData := resArgs[0].Interface() rErr := resArgs[1].Interface() if erErr, ok := rErr.(error); ok { return rData, erErr } return rData, nil } } }
// WrapStreamHandler wraps a handler returning a StreamHandler. func WrapStreamHandler(h interface{}) StreamHandler { switch h.(type) { case func(context.Context, error, interface{}) (interface{}, error): return func(ctx context.Context, data interface{}, end bool) interface{} { if ed, ok := data.(error); ok { res, err := (h.(func(context.Context, error, interface{}) (interface{}, error)))(ctx, ed, nil) if err != nil { return err } return res } res, err := (h.(func(context.Context, error, interface{}) (interface{}, error)))(ctx, nil, data) if err != nil { return err } return res } case func(context.Context, interface{}, bool) interface{}: return h.(func(context.Context, interface{}, bool) interface{}) default: if !reflection.IsFuncType(h) { return nil } tm, _ := reflection.FuncValue(h) args, _ := reflection.GetFuncArgumentsType(h) dLen := len(args) var data reflect.Type var dZero reflect.Value var useContext bool var useBool bool var useData bool // var isCustom bool // Check if this first item is a context.Context type. if dLen < 2 { useContext, _ = reflection.CanSetForType(ctxType, args[0]) useBool, _ = reflection.CanSetForType(boolType, args[0]) if !useBool { data = args[0] dZero = reflect.Zero(data) useData = true // isCustom = true } } if dLen == 2 { useContext, _ = reflection.CanSetForType(ctxType, args[0]) useBool, _ = reflection.CanSetForType(boolType, args[1]) if !useBool { data = args[1] dZero = reflect.Zero(data) useData = true // isCustom = true } } if dLen > 2 { useContext, _ = reflection.CanSetForType(ctxType, args[0]) useBool, _ = reflection.CanSetForType(boolType, args[2]) data = args[1] dZero = reflect.Zero(data) useData = true } return func(ctx context.Context, val interface{}, done bool) interface{} { var fnArgs []reflect.Value var resArgs []reflect.Value var mctx reflect.Value me := reflect.ValueOf(done) md := dZero if useContext { mctx = reflect.ValueOf(ctx) } // Flag to skip function if data does not match. breakOfData := true if val != nil && useData { ok, convertData := reflection.CanSetForType(data, reflect.TypeOf(val)) if ok { breakOfData = false md = reflect.ValueOf(val) if convertData { md = md.Convert(data) } } } if !useContext && !useData && !useBool { resArgs = tm.Call(nil) } else { // If data does not match then skip this fall. if breakOfData && len(fnArgs) < 1 { return nil } if !breakOfData { if useContext && useBool && useData { fnArgs = []reflect.Value{mctx, md, me} } if useContext && !useBool && useData { fnArgs = []reflect.Value{mctx, md} } if !useContext && useData && useBool { fnArgs = []reflect.Value{md, me} } if !useContext && useData && !useBool { fnArgs = []reflect.Value{md} } } resArgs = tm.Call(fnArgs) } resLen := len(resArgs) if resLen < 1 { return nil } return resArgs[0].Interface() } } }