1use crate::{Response, ResponsePayload, RpcError, RpcRecv};
2use serde_json::value::RawValue;
3use std::{any::TypeId, borrow::Borrow};
4
5pub type RpcResult<T, E, ErrResp = Box<RawValue>> = Result<T, RpcError<E, ErrResp>>;
19
20pub type BorrowedRpcResult<'a, E> = RpcResult<&'a RawValue, E, &'a RawValue>;
22
23pub fn transform_response<T, E, ErrResp>(response: Response<T, ErrResp>) -> RpcResult<T, E, ErrResp>
27where
28 ErrResp: RpcRecv,
29{
30 match response {
31 Response { payload: ResponsePayload::Failure(err_resp), .. } => {
32 Err(RpcError::err_resp(err_resp))
33 }
34 Response { payload: ResponsePayload::Success(result), .. } => Ok(result),
35 }
36}
37
38pub fn transform_result<T, E, ErrResp>(
42 response: Result<Response<T, ErrResp>, E>,
43) -> Result<T, RpcError<E, ErrResp>>
44where
45 ErrResp: RpcRecv,
46{
47 match response {
48 Ok(resp) => transform_response(resp),
49 Err(e) => Err(RpcError::Transport(e)),
50 }
51}
52
53pub fn try_deserialize_ok<J, T, E, ErrResp>(
55 result: RpcResult<J, E, ErrResp>,
56) -> RpcResult<T, E, ErrResp>
57where
58 J: Borrow<RawValue> + 'static,
59 T: RpcRecv,
60 ErrResp: RpcRecv,
61{
62 let json = result?;
63
64 if TypeId::of::<J>() == TypeId::of::<Box<RawValue>>()
68 && TypeId::of::<T>() == TypeId::of::<Box<RawValue>>()
69 {
70 let json = std::mem::ManuallyDrop::new(json);
73 return Ok(unsafe { std::mem::transmute_copy::<J, T>(&json) });
74 }
75
76 let _guard = debug_span!("deserialize_response", ty=%std::any::type_name::<T>()).entered();
77 let json = json.borrow().get();
78 trace!(%json, "deserializing");
79 serde_json::from_str(json)
80 .inspect(|response| trace!(?response, "deserialized"))
81 .inspect_err(|err| trace!(?err, "failed to deserialize"))
82 .map_err(|err| RpcError::deser_err(err, json))
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use serde_json::value::to_raw_value;
89
90 #[test]
91 fn raw_value_success_returns_payload_without_reencoding() {
92 let src = "{ \"a\" :1,\"b\": [ 2 ,3 ] }";
95 let raw = RawValue::from_string(src.to_owned()).unwrap();
96 let ptr = raw.get().as_ptr();
97 let input: RpcResult<Box<RawValue>, (), Box<RawValue>> = Ok(raw);
98
99 let out = try_deserialize_ok::<_, Box<RawValue>, (), Box<RawValue>>(input).unwrap();
100
101 assert_eq!(out.get(), src);
102 assert_eq!(out.get().as_ptr(), ptr);
104 }
105
106 #[test]
107 fn generic_deserialize_path_unchanged() {
108 let raw = to_raw_value(&42u64).unwrap();
109 let input: RpcResult<Box<RawValue>, (), Box<RawValue>> = Ok(raw);
110 let out = try_deserialize_ok::<_, u64, (), Box<RawValue>>(input).unwrap();
111 assert_eq!(out, 42);
112 }
113}