3 | import JSON.Simple.Derive
5 | import public Data.Singleton
6 | import Data.List.Quantifiers
8 | import Decidable.Equality
10 | %language ElabReflection
13 | IgnoreMissingKeyToJSON : List Name -> ParamTypeInfo -> Res (List TopLevel)
14 | IgnoreMissingKeyToJSON = customFromJSON Export ({replaceMissingKeysWithNull := const True} defaultOptions)
16 | IgnoreMissingKeyFromJSON : List Name -> ParamTypeInfo -> Res (List TopLevel)
17 | IgnoreMissingKeyFromJSON = customToJSON Export ({replaceMissingKeysWithNull := const True} defaultOptions)
19 | IgnoreMissingParamFromJSON : List Name -> ParamTypeInfo -> Res (List TopLevel)
20 | IgnoreMissingParamFromJSON =
21 | customFromJSON Export ({replaceMissingKeysWithNull := (== "params")} defaultOptions)
23 | UntaggedFromJSON : List Name -> ParamTypeInfo -> Res (List TopLevel)
24 | UntaggedFromJSON = customFromJSON Export ({sum := UntaggedValue} defaultOptions)
26 | UntaggedToJSON : List Name -> ParamTypeInfo -> Res (List TopLevel)
27 | UntaggedToJSON = customToJSON Export ({sum := UntaggedValue} defaultOptions)
31 | record JSONObject where
32 | constructor MkJSONObject
33 | toList : List (String, JSON)
35 | %runElab derive "JSONObject" [Eq]
37 | public export %inline
38 | fromList : List (String, JSON) -> JSONObject
39 | fromList = MkJSONObject
42 | FromJSON JSONObject where
43 | fromJSON (JObject ls) = MkJSONObject <$> traverse (traverse fromJSON) ls
44 | fromJSON _ = fail "expected JSON object"
47 | ToJSON JSONObject where
48 | toJSON (MkJSONObject ls) = JObject ls
51 | Show JSONObject where
55 | Interpolation JSONObject where
56 | interpolate x = encode x
61 | JSONArray = List JSON
76 | Interpolation Null where
77 | interpolate _ = "null"
81 | decEq MkNull MkNull = Yes Refl
89 | fromJSON JNull = pure MkNull
91 | fail "expected null, but encountered \{typeOf actual}"
95 | data JSONRPCId : Type where
96 | IntegerId : Integer -> JSONRPCId
97 | StringId : String -> JSONRPCId
98 | NullId : Null -> JSONRPCId
100 | public export %inline
102 | NoId = NullId MkNull
104 | %runElab derive "JSONRPCId"
105 | [Eq, UntaggedToJSON, UntaggedFromJSON]
108 | Show JSONRPCId where
112 | data Parameters : Type where
113 | NullParam : Null -> Parameters
114 | ByPosition : JSONArray -> Parameters
115 | ByName : JSONObject -> Parameters
117 | public export %inline
118 | ByName' : List (String, JSON) -> Parameters
119 | ByName' = ByName . MkJSONObject
124 | ByNameFromJSON : JSON -> Parameters
125 | ByNameFromJSON (JObject fields) = ByName (MkJSONObject fields)
126 | ByNameFromJSON _ = ByName (MkJSONObject [])
128 | %runElab derive "Parameters"
129 | [Eq, UntaggedToJSON, UntaggedFromJSON]
131 | public export %inline
132 | NoParam : Parameters
133 | NoParam = NullParam MkNull
135 | public export %inline
136 | Named : List (String, JSON) -> Parameters
137 | Named = ByName . MkJSONObject
140 | Show Parameters where
144 | record Request where
145 | constructor MkRequest'
146 | jsonrpc : Singleton "2.0"
148 | params : Parameters
151 | %runElab derive "Request" [ Eq, ToJSON, IgnoreMissingParamFromJSON ]
158 | Interpolation Request where
159 | interpolate x = encode x
161 | public export %inline
162 | MkRequest : String -> Parameters -> JSONRPCId -> Request
163 | MkRequest = MkRequest' (Val "2.0")
167 | record Notification where
168 | constructor MkNotification'
169 | jsonrpc : Singleton "2.0"
171 | params : Parameters
173 | %runElab derive "Notification" [ Eq, ToJSON, IgnoreMissingParamFromJSON ]
176 | Show Notification where
180 | Interpolation Notification where
181 | interpolate x = encode x
183 | public export %inline
184 | MkNotification : String -> Parameters -> Notification
185 | MkNotification = MkNotification' (Val "2.0")
189 | record ResponseSuccess where
190 | constructor MkResponseSuccess'
191 | jsonrpc : Singleton "2.0"
195 | %runElab derive "ResponseSuccess" [ Eq, ToJSON, FromJSON ]
198 | Show ResponseSuccess where
202 | Interpolation ResponseSuccess where
203 | interpolate x = encode x
205 | public export %inline
206 | MkResponseSuccess : JSON -> JSONRPCId -> ResponseSuccess
207 | MkResponseSuccess = MkResponseSuccess' (Val "2.0")
218 | | ServerError Integer
219 | | CustomError Integer
221 | %runElab derive "ErrorCode" [ Eq, Ord ]
224 | FromJSON ErrorCode where
225 | fromJSON (JInteger (-
32700)) = pure $
ParseError
226 | fromJSON (JInteger (-
32600)) = pure $
InvalidRequest
227 | fromJSON (JInteger (-
32601)) = pure $
MethodNotFound
228 | fromJSON (JInteger (-
32602)) = pure $
InvalidParams
229 | fromJSON (JInteger (-
32603)) = pure $
InternalError
230 | fromJSON (JInteger n) =
231 | case (n >= -
32099 && n <= (-
32000)) of
232 | True => pure $
ServerError n
233 | _ => pure $
CustomError n
234 | fromJSON _ = fail "not an integer"
237 | (.code) : ErrorCode -> Integer
238 | (.code) ParseError = (-
32700)
239 | (.code) InvalidRequest = (-
32600)
240 | (.code) MethodNotFound = (-
32601)
241 | (.code) InvalidParams = (-
32602)
242 | (.code) InternalError = (-
32603)
243 | (.code) (ServerError i) = i
244 | (.code) (CustomError i) = i
247 | ToJSON ErrorCode where
248 | toJSON x = JInteger x.code
251 | Show ErrorCode where
252 | show x = show x.code
255 | Interpolation ErrorCode where
256 | interpolate x = show x.code
260 | constructor MkError
265 | mapData : String -> String
266 | mapData "data_" = "data"
269 | %runElab derive "Error" [ customToJSON Export ({fieldNameModifier := mapData} defaultOptions)]
271 | nothingEqNull : Maybe JSON -> Maybe JSON -> Bool
272 | nothingEqNull Nothing Nothing = True
273 | nothingEqNull (Just JNull) Nothing = True
274 | nothingEqNull Nothing (Just JNull) = True
275 | nothingEqNull (Just x) (Just y) = x == y
276 | nothingEqNull _ _ = False
280 | MkError c1 m1 d1 == MkError c2 m2 d2 = c1 == c2 && m1 == m2 && nothingEqNull d1 d2
284 | FromJSON Error where
285 | fromJSON (JObject xs) = do
286 | let Just code = lookup "code" xs
287 | | Nothing => fail #"expected field "code""#
288 | let Just message = lookup "message" xs
289 | | Nothing => fail #"expected field "message""#
291 | data_ <- traverse fromJSON (lookup "data" xs )
294 | !(fromJSON message)
296 | fromJSON _ = fail "expected object"
303 | Interpolation Error where
304 | interpolate x = encode x
308 | record ResponseError where
309 | constructor MkResponseError'
310 | jsonrpc : Singleton "2.0"
314 | %runElab derive "ResponseError" [ Eq, ToJSON, FromJSON ]
317 | Show ResponseError where
321 | Interpolation ResponseError where
322 | interpolate x = encode x
324 | public export %inline
325 | MkResponseError : Error -> JSONRPCId -> ResponseError
326 | MkResponseError = MkResponseError' (Val "2.0")
329 | data Response : Type where
330 | Success : ResponseSuccess -> Response
331 | Failure : ResponseError -> Response
334 | rpcSuccessResponse :
338 | rpcSuccessResponse requestID result
339 | = Success $
MkResponseSuccess (toJSON result) requestID
341 | %runElab derive "Response"
342 | [Eq, UntaggedToJSON, UntaggedFromJSON]
345 | Show Response where
351 | data Message : Type where
352 | Req : Request -> Message
353 | Notif : Notification -> Message
355 | %runElab derive "Message"
356 | [Eq, UntaggedToJSON, UntaggedFromJSON]
363 | Interpolation Message where
364 | interpolate x = encode x
368 | JSONRPCBatch : Type
369 | JSONRPCBatch = List (Maybe Message)
377 | rpcJSONParseError : ResponseError
378 | rpcJSONParseError =
380 | (MkError ParseError "Parse error" Nothing) NoId
384 | rpcInvalidRequestError : ResponseError
385 | rpcInvalidRequestError =
387 | (MkError InvalidRequest "Invalid Request" Nothing) NoId
392 | rpcMissingMethod : JSONRPCId -> ResponseError
393 | rpcMissingMethod = MkResponseError (MkError MethodNotFound "Method not found" Nothing)