package json import ( "encoding/json" "fmt" "io" "git.loafle.net/commons_go/rpc/codec" "git.loafle.net/commons_go/rpc/protocol" ) // ---------------------------------------------------------------------------- // ClientResponseCodec // ---------------------------------------------------------------------------- // clientResponse represents a JSON-RPC response returned to a client. type clientResponse struct { Version string `json:"jsonrpc"` Result *json.RawMessage `json:"result,omitempty"` Error error `json:"error,omitempty"` ID interface{} `json:"id,omitempty"` } // ClientResponseCodec decodes and encodes a single request. type ClientResponseCodec struct { res *clientResponse err error codec codec.Codec } func (crc *ClientResponseCodec) ID() interface{} { return crc.res.ID } func (crc *ClientResponseCodec) Result(result interface{}) error { if nil == crc.err && nil != crc.res.Result { if err := json.Unmarshal(*crc.res.Result, result); nil != err { crc.err = &Error{ Code: E_PARSE, Message: err.Error(), Data: crc.res.Result, } } } return crc.err } func (crc *ClientResponseCodec) Error() error { return crc.res.Error } func (crc *ClientResponseCodec) Notification() (protocol.ClientNotificationCodec, error) { if nil != crc.res.ID || nil == crc.res.Result { return nil, fmt.Errorf("RPC[JSON]: This is not notification") } noti := &clientNotification{} err := json.Unmarshal(*crc.res.Result, noti) if nil != err { return nil, err } return &ClientNotificationCodec{noti: noti, err: err, codec: crc.codec}, nil } // newClientMessageCodec returns a new ClientMessageCodec. func newClientResponseCodec(r io.Reader, codec codec.Codec) (protocol.ClientResponseCodec, error) { decoder := json.NewDecoder(r) if nil == r { return nil, io.EOF } res := &clientResponse{} err := decoder.Decode(res) if err != nil { if err == io.ErrUnexpectedEOF || err == io.EOF { return nil, err } err = &Error{ Code: E_PARSE, Message: err.Error(), Data: res, } } if res.Version != Version { err = &Error{ Code: E_INVALID_REQ, Message: "jsonrpc must be " + Version, Data: res, } } return &ClientResponseCodec{res: res, err: err, codec: codec}, nil }