///|
/// Message covers all jsonrpc2 message types.
/// They share no common functionality, but are a closed set of concrete types
/// that are allowed to implement this interface. The message types are Request
/// and Response.
pub enum Message {
// Request is a jsonrpc2 request message.
Request(Request)
// Response is a jsonrpc2 response message.
Response(Response)
// BatchRequest is an array of requests.
BatchRequest(Array[Request])
// BatchResponse is an array of responses.
BatchResponse(Array[Response])
} derive(Debug, Eq)
///|
pub impl Show for Message with fn output(self, logger) {
match self {
Request(req) =>
logger.write_string(
(
$|Request(\{req.to_string()})
),
)
Response(res) =>
logger.write_string(
(
$|Response(\{res.to_string()})
),
)
BatchRequest(arr_req) =>
logger.write_string(
(
$|BatchRequest(\{Repr(arr_req).to_string()})
),
)
BatchResponse(arr_res) =>
logger.write_string(
(
$|BatchResponse(\{Repr(arr_res).to_string()})
),
)
}
}
///|
test "Message show interface" {
let m1 = new_notification("m", { "a": "b" }.to_json())
inspect(
m1,
content=(
#|Request({id: None, method_: "m", params: Object({ "a": String("b") })})
),
)
let m2 = new_call(ID::string("2"), "m", { "a": "b" }.to_json())
inspect(
m2,
content=(
#|Request({id: Some(String("2")), method_: "m", params: Object({ "a": String("b") })})
),
)
let m3 = new_response(ID::number(3), Ok({ "a": "b" }.to_json()))
inspect(
m3,
content=(
#|Response({id: Number(3), result: Ok(Object({ "a": String("b") }))})
),
)
let m4 = new_batch_request([m1, m2])
inspect(
m4,
content=(
#|BatchRequest([
#| { id: None, method_: "m", params: Object({ "a": String("b") }) },
#| {
#| id: Some(String("2")),
#| method_: "m",
#| params: Object({ "a": String("b") }),
#| },
#|])
),
)
let m5 = new_batch_response([m1, m2, m3])
inspect(
m5,
content=(
#|BatchResponse([{ id: Number(3), result: Ok(Object({ "a": String("b") })) }])
),
)
}
///|
pub impl ToJson for Message with fn to_json(self) {
match self {
Request(req) => req.to_json()
Response(res) => res.to_json()
BatchRequest(arr_req) => arr_req.to_json()
BatchResponse(arr_res) => arr_res.to_json()
}
}
///|
pub impl @json.FromJson for Message with fn from_json(json, path) {
try {
return Request(@json.from_json(json, path~))
} catch {
_ => ()
}
try {
return Response(@json.from_json(json, path~))
} catch {
_ => ()
}
try {
return BatchRequest(@json.from_json(json, path~))
} catch {
_ => ()
}
try {
return BatchResponse(@json.from_json(json, path~))
} catch {
_ => ()
}
raise @json.JsonDecodeError((path, "expected request(s) or response(s)"))
}
///|
/// new_notification constructs a new notification message for the supplied
/// method and parameters.
pub fn new_notification(method_ : String, params : Json) -> Message {
Request({ id: None, method_, params })
}
///|
/// new_call constructs a new call message for the supplied ID, method and
/// parameters.
pub fn new_call(id : ID, method_ : String, params : Json) -> Message {
Request({ id: Some(id), method_, params })
}
///|
/// new_response constructs a new Response message.
pub fn new_response(id : ID, result : Result[Json, WireError]) -> Message {
Response({ id, result })
}
///|
/// new_batch_request constructs a new batch request message for the supplied
/// requests.
pub fn new_batch_request(messages : Array[Message]) -> Message {
let requests = messages.filter_map(Message::as_request)
BatchRequest(requests)
}
///|
/// new_batch_response constructs a new batch response message for the supplied
/// responses.
pub fn new_batch_response(messages : Array[Message]) -> Message {
let responses = messages.filter_map(Message::as_response)
BatchResponse(responses)
}
///|
pub fn Message::as_call(self : Message) -> Request? {
guard self is Request(req) else { return None }
guard req.id is Some(_) else { return None }
Some(req)
}
///|
pub fn Message::as_notification(self : Message) -> Request? {
guard self is Request(req) else { return None }
guard req.id is None else { return None }
Some(req)
}
///|
pub fn Message::as_request(self : Message) -> Request? {
if self is Request(req) {
Some(req)
} else {
None
}
}
///|
pub fn Message::as_response(self : Message) -> Response? {
if self is Response(res) {
Some(res)
} else {
None
}
}
///|
/// as_batch_request returns the message as a batch request if it is one.
pub fn Message::as_batch_request(self : Message) -> Array[Request]? {
if self is BatchRequest(arr_req) {
Some(arr_req)
} else {
None
}
}
///|
/// as_batch_response returns the message as a batch response if it is one.
pub fn Message::as_batch_response(self : Message) -> Array[Response]? {
if self is BatchResponse(arr_res) {
Some(arr_res)
} else {
None
}
}