package jrpc import ( "context" "strings" json "github.com/goccy/go-json" jsoniter "github.com/json-iterator/go" ) type Request struct { Version version `json:"jsonrpc"` ID *ID `json:"id,omitempty"` Method string `json:"method"` Params json.RawMessage `json:"params"` Peer PeerInfo `json:"-"` ctx context.Context } func NewMsgRequest(ctx context.Context, peer PeerInfo, msg jsonrpcMessage) *Request { r := &Request{ctx: ctx} r.ID = msg.ID r.Method = msg.Method r.Params = msg.Params r.Peer = peer r.ctx = ctx return r } func NewRequest(ctx context.Context, id string, method string, params any) *Request { r := &Request{ctx: ctx} pms, _ := json.Marshal(params) r.ID = NewStringIDPtr(id) r.Method = method r.Params = pms return r } func (r *Request) ParamSlice() []any { var params []any json.Unmarshal(r.Params, ¶ms) return params } func (r *Request) makeError(err error) *jsonrpcMessage { m := r.Msg() return m.errorResponse(err) } // DEPRECATED // TODO: use our router to do this? jrpc.Namespace(string) (string, string) maybe? func (r *Request) namespace() string { elem := strings.SplitN(r.Method, serviceMethodSeparator, 2) return elem[0] } func (r *Request) errorResponse(err error) *Response { mw := NewReaderResponseWriterMsg(r) mw.Send(nil, err) return mw.Response() } func (r *Request) isSubscribe() bool { return strings.HasSuffix(r.Method, subscribeMethodSuffix) } func (r *Request) isUnsubscribe() bool { return strings.HasSuffix(r.Method, unsubscribeMethodSuffix) } func (r *Request) isNotification() bool { return r.ID == nil && len(r.Method) > 0 } func (r *Request) isCall() bool { return r.hasValidID() && len(r.Method) > 0 } func (r *Request) isResponse() bool { return false } func (r *Request) hasValidID() bool { return r.ID != nil && !r.ID.null } func (r *Request) ParamArray(a ...any) error { var params []json.RawMessage json.Unmarshal(r.Params, ¶ms) for idx, v := range params { if len(v) > idx { err := json.Unmarshal(v, &a[idx]) if err != nil { return err } } else { break } } return nil } func (r *Request) ParamInto(v any) error { return json.Unmarshal(r.Params, &v) } func (r *Request) Context() context.Context { return r.ctx } func (r *Request) Msg() jsonrpcMessage { return jsonrpcMessage{ ID: r.ID, Method: r.Method, Params: r.Params, } } func (r *Request) Remote() string { return r.Peer.RemoteAddr } func (r *Request) WithContext(ctx context.Context) *Request { if ctx == nil { panic("nil context") } r.ctx = ctx r2 := new(Request) *r2 = *r r2.ctx = ctx r2.ID = r.ID r2.Method = r.Method r2.Params = r.Params r2.Peer = r.Peer return r2 } var jpool = jsoniter.NewIterator(jsoniter.ConfigCompatibleWithStandardLibrary).Pool() func (r *Request) Iter(fn func(j *jsoniter.Iterator) error) error { it := jpool.BorrowIterator(r.Params) defer jpool.ReturnIterator(it) return fn(it) }