package rpc import ( "bytes" "encoding/binary" "errors" "git.nspix.com/golang/micro/gateway/rpc/codec" "git.nspix.com/golang/micro/utils/unsafestr" "io" ) const ( SuccessCode = 0 ) type Response struct { codec codec.Codec code uint16 //状态码 message string //错误消息 error error //错误实体 Body []byte //内容 } //获取状态码 func (r *Response) StatusCode() int { return int(r.code) } //获取错误 func (r *Response) Error() (err error) { if r.error != nil { return r.error } if r.code != SuccessCode { r.error = errors.New(r.message) err = r.error } return } func (r *Response) SetBody(i interface{}) (err error) { r.Body, err = r.codec.Encode(i) return } //解码内容 func (r *Response) Decode(i interface{}) (err error) { return r.codec.Decode(r.Body, i) } func (r *Response) Bytes() []byte { buf := &bytes.Buffer{} if _, err := r.WriteTo(buf); err == nil { return buf.Bytes() } return nil } // |--code--|--msg length--|--body length--|--msg--|--body--| // |-- 2 --|-- 2 ----------| --2-----------| func (r *Response) WriteTo(w io.Writer) (n int64, err error) { var ( m int ) if err = binary.Write(w, binary.LittleEndian, r.code); err != nil { return } n += 2 msgLen := len(r.message) bodyLen := len(r.Body) if err = binary.Write(w, binary.LittleEndian, uint16(msgLen)); err != nil { return } n += 2 if err = binary.Write(w, binary.LittleEndian, uint16(bodyLen)); err != nil { return } n += 2 if m, err = w.Write(unsafestr.StringToBytes(r.message)); err == nil { n += int64(m) } if m, err = w.Write(r.Body); err == nil { n += int64(m) } return } func ReadResponse(b []byte) (resp *Response, err error) { resp = &Response{ codec: codec.DefaultCodec, } if b == nil || len(b) <= 6 { err = io.ErrShortBuffer return } var ( p []byte msgLen uint16 bodyLen uint16 ) resp.code = binary.LittleEndian.Uint16(b[:2]) msgLen = binary.LittleEndian.Uint16(b[2:4]) bodyLen = binary.LittleEndian.Uint16(b[4:6]) p = b[6:] if msgLen > 0 { if len(p) < int(msgLen) { err = io.ErrShortBuffer return } resp.message = unsafestr.BytesToString(p[:msgLen]) p = p[msgLen:] } if bodyLen > 0 { if len(p) < int(bodyLen) { err = io.ErrShortBuffer return } resp.Body = p[:bodyLen] } return } func NewResponse() *Response { return &Response{ codec: codec.DefaultCodec, } }