package jrpc import ( "context" "encoding/json" ) type HandlerFunc func(w ResponseWriter, r *Request) type Handler interface { ServeRPC(w ResponseWriter, r *Request) } type ResponseWriter interface { Send(v any, err error) error Notify(v any) error } func (fn HandlerFunc) ServeRPC(w ResponseWriter, r *Request) { (fn)(w, r) } type Request struct { ctx context.Context msg jsonrpcMessage peer PeerInfo } func NewRequest(ctx context.Context, id string, method string, params any) *Request { r := &Request{ctx: ctx} pms, _ := jzon.Marshal(params) r.msg = jsonrpcMessage{ ID: NewStringIDPtr(id), Method: method, Params: pms, } return r } func (r *Request) Method() string { return r.msg.Method } func (r *Request) Params() json.RawMessage { return r.msg.Params } func (r *Request) ParamSlice() []any { var params []any jzon.Unmarshal(r.msg.Params, ¶ms) return params } func (r *Request) ParamArray(a ...any) error { var params []json.RawMessage jzon.Unmarshal(r.msg.Params, ¶ms) for idx, v := range params { if len(v) > idx { err := jzon.Unmarshal(v, &a[idx]) if err != nil { return err } } else { break } } return nil } func (r *Request) ParamInto(v any) error { return jzon.Unmarshal(r.msg.Params, &v) } func (r *Request) Context() context.Context { return r.ctx } func (r *Request) Remote() string { return r.peer.RemoteAddr } func (r *Request) Peer() PeerInfo { return r.peer } 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.msg = r.msg return r2 } func (r *Request) Msg() jsonrpcMessage { return r.msg } type ResponseWriterMsg struct { r *Request msg *jsonrpcMessage notifications chan *jsonrpcMessage } func NewReaderResponseWriterMsg(r *Request) *ResponseWriterMsg { rw := &ResponseWriterMsg{ r: r, } switch r.Peer().Transport { case "http": default: rw.notifications = make(chan *jsonrpcMessage, 128) } return rw } func (w *ResponseWriterMsg) Send(args any, e error) (err error) { cm := w.r.Msg() if e != nil { w.msg = cm.errorResponse(e) return nil } w.msg = cm.response(args) if w.notifications != nil { close(w.notifications) } return nil } func (w *ResponseWriterMsg) Notify(args any) (err error) { if w.notifications == nil { return nil } cm := w.r.Msg() nf := cm.response(args) nf.ID = nil w.notifications <- nf return nil } func (w *ResponseWriterMsg) Result() *jsonrpcMessage { return w.msg }