1 // Copyright 2018 Adam S Levy
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to
5 // deal in the Software without restriction, including without limitation the
6 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 // sell copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 // IN THE SOFTWARE.
20 21 package jsonrpc2
22 23 import (
24 "encoding/json"
25 "fmt"
26 )
27 28 // validateID assumes that id is valid JSON and returns true if len(id) == 0,
29 // or id represents a JSON Number, String or Null.
30 //
31 // From the JSONRPC 2.0 Spec:
32 //
33 // id
34 // An identifier established by the Client that MUST contain a String,
35 // Number, or NULL value if included.
36 //
37 // Below is the JSON grammar for String, Number and Null from JSON.org.
38 // value
39 // string
40 // number
41 // "null"
42 //
43 // string
44 // '"' characters '"'
45 //
46 // number
47 // integer fraction exponent
48 //
49 // integer
50 // digit
51 // onenine digits
52 // '-' digit
53 // '-' onenine digits
54 //
55 // digits
56 // digit
57 // digit digits
58 //
59 // digit
60 // '0'
61 // onenine
62 //
63 // onenine
64 // '1' . '9'
65 //
66 // fraction
67 // ""
68 // '.' digits
69 //
70 // exponent
71 // ""
72 // 'E' sign digits
73 // 'e' sign digits
74 //
75 // Thus if we know that we are working with valid JSON, we can determine the
76 // JSON type by the first byte alone.
77 func validateID(id json.RawMessage) error {
78 if len(id) == 0 {
79 return fmt.Errorf(`invalid "id": empty`)
80 }
81 b := id[0]
82 if b == 'n' || // null
83 b == '"' || // string
84 isNumber(b) {
85 return nil
86 }
87 return fmt.Errorf(`invalid "id": not a number, string, or null`)
88 }
89 90 func isNumber(b byte) bool {
91 if b == '-' || ('0' <= b && b <= '9') || // integer
92 b == 'E' || b == 'e' || // exponent
93 b == '.' { // fraction
94 return true
95 }
96 return false
97 }
98 99 // validateParams assumes that params is valid JSON and returns true if params is
100 // nil, or if it represents a structured value (Array or Object), or Null.
101 //
102 // From the JSONRPC 2.0 Spec:
103 //
104 // params
105 // A Structured value that holds the parameter values to be used during
106 // the invocation of the method. This member MAY be omitted.
107 //
108 // Below is the JSON grammar for Object, Array and Null from JSON.org.
109 // value
110 // object
111 // array
112 // "null"
113 //
114 // object
115 // '{' ws '}'
116 // '{' members '}'
117 //
118 // array
119 // '[' ws ']'
120 // '[' elements ']'
121 //
122 // Thus if we know that we are working with valid JSON, we can determine the
123 // JSON type by the first byte alone.
124 func validateParams(params json.RawMessage) error {
125 if len(params) == 0 {
126 return fmt.Errorf(`invalid "params": empty`)
127 }
128 b := params[0]
129 if b == 'n' || // null
130 b == '[' || // array
131 b == '{' { // object
132 return nil
133 }
134 return fmt.Errorf(`invalid "params": not an object, array, or null`)
135 }
136