github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/ginx/anyfn/anyfn.go (about)

     1  package anyfn
     2  
     3  import (
     4  	"log"
     5  	"reflect"
     6  
     7  	"github.com/bingoohuang/gg/pkg/ginx/adapt"
     8  	"github.com/gin-gonic/gin"
     9  	"github.com/sirupsen/logrus"
    10  )
    11  
    12  // DirectDealer is the dealer for a specified type.
    13  type DirectDealer interface {
    14  	Deal(*gin.Context)
    15  }
    16  
    17  // HTTPStatus defines the type of HTTP state.
    18  type HTTPStatus int
    19  
    20  func (h HTTPStatus) Deal(c *gin.Context) {
    21  	c.Status(int(h))
    22  }
    23  
    24  type Adapter struct {
    25  	InSupports  []InSupport
    26  	OutSupports []OutSupport
    27  }
    28  
    29  func (a *Adapter) Default(relativePath string) adapt.Handler { return nil }
    30  
    31  func (a *Adapter) Adapt(relativePath string, argV interface{}) adapt.Handler {
    32  	anyF, ok := argV.(*anyF)
    33  	if !ok {
    34  		return nil
    35  	}
    36  
    37  	fv := reflect.ValueOf(anyF.F)
    38  
    39  	return adapt.HandlerFunc(func(c *gin.Context) {
    40  		if err := a.internalAdapter(c, fv, anyF); err != nil {
    41  			logrus.Warnf("adapt error %v", err)
    42  		}
    43  	})
    44  }
    45  
    46  func NewAdapter() *Adapter {
    47  	adapter := &Adapter{
    48  		InSupports: []InSupport{
    49  			InSupportFn(GinContextSupport),
    50  			InSupportFn(HTTPRequestSupport),
    51  			InSupportFn(HTTPResponseWriterSupport),
    52  			InSupportFn(ContextKeyValuesSupport),
    53  			InSupportFn(SinglePrimitiveValueSupport), //  try single param
    54  			InSupportFn(BindSupport),                 //  try bind
    55  		},
    56  		OutSupports: []OutSupport{
    57  			OutSupportFn(ErrorSupport),
    58  			OutSupportFn(DirectDealerSupport),
    59  			OutSupportFn(DefaultSupport),
    60  		},
    61  	}
    62  
    63  	return adapter
    64  }
    65  
    66  type Before interface {
    67  	// Do will be called Before the adaptee invoking.
    68  	Do(args []interface{}) error
    69  }
    70  
    71  type BeforeFn func(args []interface{}) error
    72  
    73  func (b BeforeFn) Do(args []interface{}) error { return b(args) }
    74  
    75  type After interface {
    76  	// Do will be called Before the adaptee invoking.
    77  	Do(args []interface{}, results []interface{}) error
    78  }
    79  
    80  type AfterFn func(args []interface{}, results []interface{}) error
    81  
    82  func (b AfterFn) Do(args []interface{}, results []interface{}) error { return b(args, results) }
    83  
    84  type anyF struct {
    85  	P      *Adapter
    86  	F      interface{}
    87  	Option *Option
    88  }
    89  
    90  func (a *anyF) Parent() adapt.Adapter { return a.P }
    91  
    92  type Option struct {
    93  	Before Before
    94  	After  After
    95  	Attrs  map[string]interface{}
    96  }
    97  
    98  type OptionFn func(*Option)
    99  
   100  func (a *Adapter) Before(before Before) OptionFn {
   101  	return func(f *Option) {
   102  		f.Before = before
   103  	}
   104  }
   105  
   106  func (a *Adapter) After(after After) OptionFn {
   107  	return func(f *Option) {
   108  		f.After = after
   109  	}
   110  }
   111  
   112  func (a *Adapter) AttrMap(attrs map[string]interface{}) OptionFn {
   113  	return func(f *Option) {
   114  		for k, v := range attrs {
   115  			f.Attrs[k] = v
   116  		}
   117  	}
   118  }
   119  
   120  func (a *Adapter) Attr(k string, v interface{}) OptionFn {
   121  	return func(f *Option) {
   122  		f.Attrs[k] = v
   123  	}
   124  }
   125  
   126  func (a *Adapter) F(v interface{}, fns ...OptionFn) adapt.Parent {
   127  	option := &Option{
   128  		Attrs: make(map[string]interface{}),
   129  	}
   130  
   131  	for _, fn := range fns {
   132  		fn(option)
   133  	}
   134  
   135  	return &anyF{F: v, Option: option}
   136  }
   137  
   138  func (a *Adapter) internalAdapter(c *gin.Context, fv reflect.Value, anyF *anyF) error {
   139  	argVs, err := a.createArgs(c, fv)
   140  	if err != nil {
   141  		return err
   142  	}
   143  
   144  	if err := a.before(argVs, anyF.Option.Before); err != nil {
   145  		return err
   146  	}
   147  
   148  	r := fv.Call(argVs)
   149  
   150  	if err := a.after(argVs, r, anyF.Option.After); err != nil {
   151  		return err
   152  	}
   153  
   154  	return a.processOut(c, fv, r)
   155  }
   156  
   157  func (a *Adapter) before(v []reflect.Value, f Before) error {
   158  	if f == nil {
   159  		return nil
   160  	}
   161  
   162  	return f.Do(Values(v).Interface())
   163  }
   164  
   165  func (a *Adapter) after(v, results []reflect.Value, f After) error {
   166  	if f == nil {
   167  		return nil
   168  	}
   169  
   170  	return f.Do(Values(v).Interface(), Values(results).Interface())
   171  }
   172  
   173  type Values []reflect.Value
   174  
   175  func (v Values) Interface() []interface{} {
   176  	args := make([]interface{}, len(v))
   177  	for i, a := range v {
   178  		args[i] = a.Interface()
   179  	}
   180  
   181  	return args
   182  }
   183  
   184  func (a *Adapter) processOut(c *gin.Context, fv reflect.Value, r []reflect.Value) error {
   185  	numOut := fv.Type().NumOut()
   186  	if numOut == 0 {
   187  		return nil
   188  	}
   189  
   190  	vs := make([]interface{}, 0, numOut)
   191  	for i := 0; i < numOut; i++ {
   192  		vs = append(vs, r[i].Interface())
   193  	}
   194  
   195  	lastErrNil := false
   196  	if numOut > 0 {
   197  		if e, ok := vs[numOut-1].(error); ok {
   198  			if e != nil {
   199  				_, err := a.processOutV(c, e, vs)
   200  				return err
   201  			} else {
   202  				lastErrNil = true
   203  			}
   204  		}
   205  	}
   206  
   207  	if lastErrNil {
   208  		vs = vs[:numOut-1]
   209  	}
   210  
   211  	for _, v := range vs {
   212  		if processed, err := a.processOutV(c, v, vs); err != nil {
   213  			return err
   214  		} else if processed {
   215  			return nil
   216  		}
   217  	}
   218  
   219  	return nil
   220  }
   221  
   222  func (a *Adapter) processOutV(c *gin.Context, v interface{}, vs []interface{}) (bool, error) {
   223  	for _, support := range a.OutSupports {
   224  		if ok, err := support.OutSupport(v, vs, c); err != nil {
   225  			return false, err
   226  		} else if ok {
   227  			return true, nil
   228  		}
   229  	}
   230  
   231  	return false, nil
   232  }
   233  
   234  func (a *Adapter) createArgs(c *gin.Context, fv reflect.Value) (v []reflect.Value, err error) {
   235  	ft := fv.Type()
   236  	argIns := parseArgIns(ft)
   237  	v = make([]reflect.Value, ft.NumIn())
   238  
   239  	for i, arg := range argIns {
   240  		if v[i], err = a.createArgValue(c, arg, argIns); err != nil {
   241  			return nil, err
   242  		}
   243  	}
   244  
   245  	return v, err
   246  }
   247  
   248  func (a *Adapter) createArgValue(c *gin.Context, arg ArgIn, argsIn []ArgIn) (reflect.Value, error) {
   249  	for _, support := range a.InSupports {
   250  		v, err := support.InSupport(arg, argsIn, c)
   251  		if err == nil && v.IsValid() {
   252  			return v, nil
   253  		} else if err != nil {
   254  			log.Printf("error parse argument %v: %v", arg, err)
   255  		}
   256  
   257  	}
   258  
   259  	return reflect.Zero(arg.Type), nil
   260  }