1
2
3
4
5 package jsonrpc2
6
7 import (
8 "encoding/json"
9 "errors"
10 "fmt"
11 )
12
13
14
15
16
17 type Message interface {
18
19
20 isJSONRPC2Message()
21 }
22
23
24
25
26 type Request interface {
27 Message
28
29 Method() string
30
31 Params() json.RawMessage
32
33 isJSONRPC2Request()
34 }
35
36
37
38 type Notification struct {
39
40 method string
41 params json.RawMessage
42 }
43
44
45
46 type Call struct {
47
48 method string
49
50 params json.RawMessage
51
52 id ID
53 }
54
55
56
57 type Response struct {
58
59 result json.RawMessage
60
61 err error
62
63 id ID
64 }
65
66
67
68 func NewNotification(method string, params interface{}) (*Notification, error) {
69 p, merr := marshalToRaw(params)
70 return &Notification{method: method, params: p}, merr
71 }
72
73 func (msg *Notification) Method() string { return msg.method }
74 func (msg *Notification) Params() json.RawMessage { return msg.params }
75 func (msg *Notification) isJSONRPC2Message() {}
76 func (msg *Notification) isJSONRPC2Request() {}
77
78 func (n *Notification) MarshalJSON() ([]byte, error) {
79 msg := wireRequest{Method: n.method, Params: &n.params}
80 data, err := json.Marshal(msg)
81 if err != nil {
82 return data, fmt.Errorf("marshaling notification: %w", err)
83 }
84 return data, nil
85 }
86
87 func (n *Notification) UnmarshalJSON(data []byte) error {
88 msg := wireRequest{}
89 if err := json.Unmarshal(data, &msg); err != nil {
90 return fmt.Errorf("unmarshaling notification: %w", err)
91 }
92 n.method = msg.Method
93 if msg.Params != nil {
94 n.params = *msg.Params
95 }
96 return nil
97 }
98
99
100
101 func NewCall(id ID, method string, params interface{}) (*Call, error) {
102 p, merr := marshalToRaw(params)
103 return &Call{id: id, method: method, params: p}, merr
104 }
105
106 func (msg *Call) Method() string { return msg.method }
107 func (msg *Call) Params() json.RawMessage { return msg.params }
108 func (msg *Call) ID() ID { return msg.id }
109 func (msg *Call) isJSONRPC2Message() {}
110 func (msg *Call) isJSONRPC2Request() {}
111
112 func (c *Call) MarshalJSON() ([]byte, error) {
113 msg := wireRequest{Method: c.method, Params: &c.params, ID: &c.id}
114 data, err := json.Marshal(msg)
115 if err != nil {
116 return data, fmt.Errorf("marshaling call: %w", err)
117 }
118 return data, nil
119 }
120
121 func (c *Call) UnmarshalJSON(data []byte) error {
122 msg := wireRequest{}
123 if err := json.Unmarshal(data, &msg); err != nil {
124 return fmt.Errorf("unmarshaling call: %w", err)
125 }
126 c.method = msg.Method
127 if msg.Params != nil {
128 c.params = *msg.Params
129 }
130 if msg.ID != nil {
131 c.id = *msg.ID
132 }
133 return nil
134 }
135
136
137
138 func NewResponse(id ID, result interface{}, err error) (*Response, error) {
139 r, merr := marshalToRaw(result)
140 return &Response{id: id, result: r, err: err}, merr
141 }
142
143 func (msg *Response) ID() ID { return msg.id }
144 func (msg *Response) Result() json.RawMessage { return msg.result }
145 func (msg *Response) Err() error { return msg.err }
146 func (msg *Response) isJSONRPC2Message() {}
147
148 func (r *Response) MarshalJSON() ([]byte, error) {
149 msg := &wireResponse{Error: toWireError(r.err), ID: &r.id}
150 if msg.Error == nil {
151 msg.Result = &r.result
152 }
153 data, err := json.Marshal(msg)
154 if err != nil {
155 return data, fmt.Errorf("marshaling notification: %w", err)
156 }
157 return data, nil
158 }
159
160 func toWireError(err error) *WireError {
161 if err == nil {
162
163 return nil
164 }
165 if err, ok := err.(*WireError); ok {
166
167 return err
168 }
169 result := &WireError{Message: err.Error()}
170 var wrapped *WireError
171 if errors.As(err, &wrapped) {
172
173
174 result.Code = wrapped.Code
175 }
176 return result
177 }
178
179 func (r *Response) UnmarshalJSON(data []byte) error {
180 msg := wireResponse{}
181 if err := json.Unmarshal(data, &msg); err != nil {
182 return fmt.Errorf("unmarshaling jsonrpc response: %w", err)
183 }
184 if msg.Result != nil {
185 r.result = *msg.Result
186 }
187 if msg.Error != nil {
188 r.err = msg.Error
189 }
190 if msg.ID != nil {
191 r.id = *msg.ID
192 }
193 return nil
194 }
195
196 func DecodeMessage(data []byte) (Message, error) {
197 msg := wireCombined{}
198 if err := json.Unmarshal(data, &msg); err != nil {
199 return nil, fmt.Errorf("unmarshaling jsonrpc message: %w", err)
200 }
201 if msg.Method == "" {
202
203 if msg.ID == nil {
204 return nil, ErrInvalidRequest
205 }
206 response := &Response{id: *msg.ID}
207 if msg.Error != nil {
208 response.err = msg.Error
209 }
210 if msg.Result != nil {
211 response.result = *msg.Result
212 }
213 return response, nil
214 }
215
216 if msg.ID == nil {
217
218 notify := &Notification{method: msg.Method}
219 if msg.Params != nil {
220 notify.params = *msg.Params
221 }
222 return notify, nil
223 }
224
225 call := &Call{method: msg.Method, id: *msg.ID}
226 if msg.Params != nil {
227 call.params = *msg.Params
228 }
229 return call, nil
230 }
231
232 func marshalToRaw(obj interface{}) (json.RawMessage, error) {
233 data, err := json.Marshal(obj)
234 if err != nil {
235 return json.RawMessage{}, err
236 }
237 return json.RawMessage(data), nil
238 }
239
View as plain text