good morning!!!!

Skip to content
Snippets Groups Projects
request.go 2.63 KiB
Newer Older
a's avatar
rpc
a committed
package jrpc

import (
	"context"
a's avatar
ok  
a committed

a's avatar
a committed
	"gfx.cafe/open/jrpc/codec"
	json "github.com/goccy/go-json"
a's avatar
ok  
a committed
	jsoniter "github.com/json-iterator/go"
a's avatar
rpc
a committed
)

a's avatar
a committed
var jpool = jsoniter.NewIterator(jsoniter.ConfigCompatibleWithStandardLibrary).Pool()

a's avatar
rpc
a committed
type Request struct {
a's avatar
a committed
	RequestMarshaling

	ctx context.Context
}

func (r *Request) UnmarshalJSON(xs []byte) error {
	return json.Unmarshal(xs, &r.RequestMarshaling)
}

func (r *Request) MarshalJSON() ([]byte, error) {
	return json.Marshal(r.RequestMarshaling)
}

type RequestMarshaling struct {
a's avatar
a committed
	Version codec.Version   `json:"jsonrpc"`
	ID      *codec.ID       `json:"id,omitempty"`
a's avatar
a committed
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params"`
a's avatar
a committed
	Peer    codec.PeerInfo  `json:"-"`
a's avatar
a committed
}
a's avatar
a committed

a's avatar
a committed
func NewRequestInt(ctx context.Context, id int, method string, params any) *Request {
	r := &Request{ctx: ctx}
	pms, _ := json.Marshal(params)
	r.ID = codec.NewNumberIDPtr(int64(id))
	r.Method = method
	r.Params = pms
	return r
a's avatar
a committed
}
a's avatar
a committed
func NewRequest(ctx context.Context, id string, method string, params any) *Request {
	r := &Request{ctx: ctx}
	pms, _ := json.Marshal(params)
a's avatar
a committed
	r.ID = codec.NewStringIDPtr(id)
a's avatar
a committed
	r.Method = method
	r.Params = pms
a's avatar
a committed
	return r
}

a's avatar
a committed
func (r *Request) makeError(err error) *codec.Message {
a's avatar
a committed
	m := r.Msg()
a's avatar
a committed
	return m.ErrorResponse(err)
a's avatar
a committed
}

a's avatar
a committed
func (r *Request) errorResponse(err error) *Response {
	mw := NewReaderResponseWriterMsg(r)
	mw.Send(nil, err)
	return mw.Response()
}
a's avatar
a committed

func (r *Request) isNotification() bool {
	return r.ID == nil && len(r.Method) > 0
}
a's avatar
a committed

a's avatar
a committed
func (r *Request) isCall() bool {
	return r.hasValidID() && len(r.Method) > 0
}
a's avatar
a committed

a's avatar
a committed
func (r *Request) hasValidID() bool {
a's avatar
a committed
	return r.ID != nil && !r.ID.IsNull()
a's avatar
a committed
}

a's avatar
a committed
func (r *Request) ParamArray(a ...any) error {
	var params []json.RawMessage
a's avatar
a committed
	json.Unmarshal(r.Params, &params)
a's avatar
a committed
	for idx, v := range params {
		if len(v) > idx {
			err := json.Unmarshal(v, &a[idx])
a's avatar
a committed
			if err != nil {
				return err
			}
		} else {
			break
		}
	}
	return nil
}

func (r *Request) ParamInto(v any) error {
a's avatar
a committed
	return json.Unmarshal(r.Params, &v)
a's avatar
rpc
a committed
func (r *Request) Context() context.Context {
	return r.ctx
}

a's avatar
a committed
func (r *Request) Msg() codec.Message {
	return codec.Message{
a's avatar
a committed
		ID:     r.ID,
		Method: r.Method,
		Params: r.Params,
	}
a's avatar
a committed
func (r *Request) Remote() string {
	return r.Peer.RemoteAddr
a's avatar
rpc
a committed
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
a's avatar
a committed
	r2.ID = r.ID
	r2.Method = r.Method
	r2.Params = r.Params
	r2.Peer = r.Peer
a's avatar
rpc
a committed
	return r2
}
a's avatar
a committed
func (r *Request) Iter(fn func(j *jsoniter.Iterator) error) error {
a's avatar
a committed
	it := jpool.BorrowIterator(r.Params)
a's avatar
a committed
	defer jpool.ReturnIterator(it)
	return fn(it)
a's avatar
a committed
}