func (c *Context) mustBindWith(obj interface{}, b binding.Binding) (err error) {
	if err = b.Bind(c.Request, obj); err != nil {
		c.Error = ecode.RequestErr
		c.Render(http.StatusOK, render.JSON{
			Code:    ecode.RequestErr.Code(),
			Message: err.Error(),
			Data:    nil,
		})
		c.Abort()
	}
	return
}
mustBindWith binds the passed struct pointer using the specified binding engine.
It will abort the request with HTTP 400 if any error ocurrs.
See the binding package.
package blademaster
import (
	"context"
	"math"
	"net/http"
	"strconv"
	"text/template"
	"github.com/mapgoo-lab/atreus/pkg/ecode"
	"github.com/mapgoo-lab/atreus/pkg/net/http/blademaster/binding"
	"github.com/mapgoo-lab/atreus/pkg/net/http/blademaster/render"
	"github.com/gogo/protobuf/proto"
	"github.com/gogo/protobuf/types"
	"github.com/pkg/errors"
)
const (
	_abortIndex int8 = math.MaxInt8 / 2
)
var (
	_openParen  = []byte("(")
	_closeParen = []byte(")")
)
type Context struct {
	context.Context
	Request *http.Request
	Writer  http.ResponseWriter
	index    int8
	handlers []HandlerFunc
	Keys map[string]interface{}
	Error error
	method string
	engine *Engine
	RoutePath string
	Params Params
}
func (c *Context) Next() {
	c.index++
	for c.index < int8(len(c.handlers)) {
		c.handlers[c.index](c)
		c.index++
	}
}
func (c *Context) Abort() {
	c.index = _abortIndex
}
func (c *Context) AbortWithStatus(code int) {
	c.Status(code)
	c.Abort()
}
func (c *Context) IsAborted() bool {
	return c.index >= _abortIndex
}
func (c *Context) Set(key string, value interface{}) {
	if c.Keys == nil {
		c.Keys = make(map[string]interface{})
	}
	c.Keys[key] = value
}
func (c *Context) Get(key string) (value interface{}, exists bool) {
	value, exists = c.Keys[key]
	return
}
func bodyAllowedForStatus(status int) bool {
	switch {
	case status >= 100 && status <= 199:
		return false
	case status == 204:
		return false
	case status == 304:
		return false
	}
	return true
}
func (c *Context) Status(code int) {
	c.Writer.WriteHeader(code)
}
func (c *Context) Render(code int, r render.Render) {
	r.WriteContentType(c.Writer)
	if code > 0 {
		c.Status(code)
	}
	if !bodyAllowedForStatus(code) {
		return
	}
	params := c.Request.Form
	cb := template.JSEscapeString(params.Get("callback"))
	jsonp := cb != ""
	if jsonp {
		c.Writer.Write([]byte(cb))
		c.Writer.Write(_openParen)
	}
	if err := r.Render(c.Writer); err != nil {
		c.Error = err
		return
	}
	if jsonp {
		if _, err := c.Writer.Write(_closeParen); err != nil {
			c.Error = errors.WithStack(err)
		}
	}
}
func (c *Context) JSON(data interface{}, err error) {
	code := http.StatusOK
	c.Error = err
	bcode := ecode.Cause(err)
	isSimple := c.engine.conf.UseSimpleJson
	if isSimple == false {
		useSimplejson := c.Request.Form.Get("useSimpleJson")
		if useSimplejson == "1" || useSimplejson == "true" {
			isSimple = true
		}
	}
	writeStatusCode(c.Writer, bcode.Code())
	c.Render(code, render.JSON{
		Code:    bcode.Code(),
		Message: bcode.Message(),
		Data:    data,
		IsSimple: isSimple,
	})
}
func (c *Context) JSONMap(data map[string]interface{}, err error) {
	code := http.StatusOK
	c.Error = err
	bcode := ecode.Cause(err)
	writeStatusCode(c.Writer, bcode.Code())
	data["code"] = bcode.Code()
	if _, ok := data["message"]; !ok {
		data["message"] = bcode.Message()
	}
	c.Render(code, render.MapJSON(data))
}
func (c *Context) XML(data interface{}, err error) {
	code := http.StatusOK
	c.Error = err
	bcode := ecode.Cause(err)
	writeStatusCode(c.Writer, bcode.Code())
	c.Render(code, render.XML{
		Code:    bcode.Code(),
		Message: bcode.Message(),
		Data:    data,
	})
}
func (c *Context) Protobuf(data proto.Message, err error) {
	var (
		bytes []byte
	)
	code := http.StatusOK
	c.Error = err
	bcode := ecode.Cause(err)
	any := new(types.Any)
	if data != nil {
		if bytes, err = proto.Marshal(data); err != nil {
			c.Error = errors.WithStack(err)
			return
		}
		any.TypeUrl = "type.googleapis.com/" + proto.MessageName(data)
		any.Value = bytes
	}
	writeStatusCode(c.Writer, bcode.Code())
	c.Render(code, render.PB{
		Code:    int64(bcode.Code()),
		Message: bcode.Message(),
		Data:    any,
	})
}
func (c *Context) Bytes(code int, contentType string, data ...[]byte) {
	c.Render(code, render.Data{
		ContentType: contentType,
		Data:        data,
	})
}
func (c *Context) String(code int, format string, values ...interface{}) {
	c.Render(code, render.String{Format: format, Data: values})
}
func (c *Context) Redirect(code int, location string) {
	c.Render(-1, render.Redirect{
		Code:     code,
		Location: location,
		Request:  c.Request,
	})
}
func (c *Context) BindWith(obj interface{}, b binding.Binding) error {
	return c.mustBindWith(obj, b)
}
func (c *Context) Bind(obj interface{}) error {
	b := binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))
	return c.mustBindWith(obj, b)
}