From 32aea5406aa5c2dba6b783cec0e22bf0bb5d4685 Mon Sep 17 00:00:00 2001 From: a <a@a.a> Date: Fri, 2 Sep 2022 20:49:31 -0500 Subject: [PATCH] add callp --- client.go | 80 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/client.go b/client.go index 5102e9d..9e77cfa 100644 --- a/client.go +++ b/client.go @@ -262,6 +262,53 @@ func (c *Client) SetHeader(key, value string) { conn.mu.Unlock() } +func (c *Client) call(ctx context.Context, result any, msg *jsonrpcMessage) error { + var err error + op := &requestOp{ids: []json.RawMessage{msg.ID.RawMessage()}, resp: make(chan *jsonrpcMessage, 1)} + + if c.isHTTP { + err = c.sendHTTP(ctx, op, msg) + } else { + err = c.send(ctx, op, msg) + } + if err != nil { + return err + } + // dispatch has accepted the request and will close the channel when it quits. + resp, err := op.wait(ctx, c) + if err != nil { + return err + } + switch { + case resp.Error != nil: + return resp.Error + case len(resp.Result) == 0: + return ErrNoResult + default: + return json.Unmarshal(resp.Result, &result) + } +} + +func (c *Client) CallP(result any, method string, param any) error { + ctx := context.Background() + return c.CallPContext(ctx, result, method, param) +} + +// CallPContext is call except it uh uses a param instead of the variadic args +// TODO: we should probably rewrite Call and CallContext to just call CallP and CallPContext +// +// i havent done this because i want to make sure that callp and callpcontext work +func (c *Client) CallPContext(ctx context.Context, result any, method string, param any) error { + if result != nil && reflect.TypeOf(result).Kind() != reflect.Ptr { + return fmt.Errorf("call result parameter must be pointer or nil interface: %v", result) + } + msg, err := c.newMessageP(method, param) + if err != nil { + return err + } + return c.call(ctx, result, msg) +} + // Call performs a JSON-RPC call with the given arguments and unmarshals into // result if no error occurred. // @@ -285,29 +332,8 @@ func (c *Client) CallContext(ctx context.Context, result any, method string, arg if err != nil { return err } - op := &requestOp{ids: []json.RawMessage{msg.ID.RawMessage()}, resp: make(chan *jsonrpcMessage, 1)} - if c.isHTTP { - err = c.sendHTTP(ctx, op, msg) - } else { - err = c.send(ctx, op, msg) - } - if err != nil { - return err - } - // dispatch has accepted the request and will close the channel when it quits. - resp, err := op.wait(ctx, c) - if err != nil { - return err - } - switch { - case resp.Error != nil: - return resp.Error - case len(resp.Result) == 0: - return ErrNoResult - default: - return json.Unmarshal(resp.Result, &result) - } + return c.call(ctx, result, msg) } // BatchCall sends all given requests as a single batch and waits for the server @@ -407,6 +433,16 @@ func (c *Client) newMessage(method string, paramsIn ...any) (*jsonrpcMessage, er } return msg, nil } +func (c *Client) newMessageP(method string, paramIn any) (*jsonrpcMessage, error) { + msg := &jsonrpcMessage{ID: c.nextID(), Method: method} + if paramIn != nil { // prevent sending "params":null + var err error + if msg.Params, err = json.Marshal(paramIn); err != nil { + return nil, err + } + } + return msg, nil +} // send registers op with the dispatch loop, then sends msg on the connection. // if sending fails, op is deregistered. -- GitLab