-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparse.go
More file actions
138 lines (120 loc) · 3.31 KB
/
parse.go
File metadata and controls
138 lines (120 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package jsoff
import (
"bytes"
"encoding/json"
)
func ParseBytes(data []byte, options ...MessageOptions) (Message, error) {
decoder := json.NewDecoder(bytes.NewReader(data))
return DecodeMessage(decoder, options...)
}
type msgUnion struct {
IdSt msgIdT `json:"id,omitempty"`
Result *json.RawMessage `json:"result,omitempty"`
Error *json.RawMessage `json:"error,omitempty"`
Params *json.RawMessage `json:"params,omitempty"`
Method string `json:"method,omitempty"`
TraceId string `json:"traceid,omitempty"`
}
type decodeErrorT struct {
errmsg string
}
func (err decodeErrorT) Error() string {
return "error decode: " + err.errmsg
}
func errdecode(errmsg string) *decodeErrorT {
return &decodeErrorT{errmsg: errmsg}
}
func decodeParams(un *msgUnion) (p []any, islist bool, e error) {
if un.Params == nil {
return nil, false, errdecode("no params field")
}
arr := []any{}
dec := json.NewDecoder(bytes.NewReader(*un.Params))
dec.UseNumber()
if err := dec.Decode(&arr); err != nil {
var intfparams any
idec := json.NewDecoder(bytes.NewReader(*un.Params))
idec.UseNumber()
if err := idec.Decode(&intfparams); err != nil {
return nil, false, err
}
return []any{intfparams}, false, nil
}
return arr, true, nil
}
func DecodeMessage(decoder *json.Decoder, options ...MessageOptions) (Message, error) {
opts := MessageOptions{}
if len(options) > 0 {
opts = options[0]
}
decoder.UseNumber()
var un msgUnion
if err := decoder.Decode(&un); err != nil {
return nil, err
}
if un.Error != nil {
// senity check
if un.Result != nil {
return nil, errdecode("result and error cannot co exist")
}
// parse error body
var errbody RPCError
errdec := json.NewDecoder(bytes.NewReader(*un.Error))
errdec.UseNumber()
if err := errdec.Decode(&errbody); err != nil {
return nil, err
}
if !un.IdSt.isSet {
return nil, errdecode("no message id")
}
errmsg := rawErrorMessage(un.IdSt.Value, &errbody, nil)
errmsg.SetTraceId(un.TraceId)
return errmsg, nil
} else if un.Result != nil {
if un.Error != nil {
return nil, errdecode("result and error cannot co exist")
}
// parse result
var res any
resdec := json.NewDecoder(bytes.NewReader(*un.Result))
resdec.UseNumber()
if err := resdec.Decode(&res); err != nil {
return nil, err
}
var msgId any = nil
if un.IdSt.isSet {
if un.IdSt.Value == nil && opts.IdNotNull {
return nil, errdecode("Result.id cannot be null")
}
msgId = un.IdSt.Value
}
resmsg := rawResultMessage(msgId, res, nil)
resmsg.SetTraceId(un.TraceId)
return resmsg, nil
} else if un.Method != "" {
params, islist, err := decodeParams(&un)
if err != nil {
return nil, err
}
if un.IdSt.isSet {
if un.IdSt.Value == nil && opts.IdNotNull {
return nil, errdecode("Request.id cannot be null")
}
reqmsg := NewRequestMessage(un.IdSt.Value, un.Method, params)
reqmsg.paramsAreList = islist
reqmsg.SetTraceId(un.TraceId)
return reqmsg, nil
} else {
ntfmsg := NewNotifyMessage(un.Method, params)
ntfmsg.paramsAreList = islist
ntfmsg.SetTraceId(un.TraceId)
return ntfmsg, nil
}
} else if un.IdSt.isSet {
// result is null
resmsg := rawResultMessage(un.IdSt.Value, nil, nil)
resmsg.SetTraceId(un.TraceId)
return resmsg, nil
}
return nil, errdecode("not a jsonrpc message")
}