我建立拉斯特库具有执行反对使用reqwest本地RPC服务器的HTTP请求一个send
方法。
这个方法返回一个R
泛型类型Result
其中R: DeserializeOwned
。作出正确的类型,每响应后,serde_json::from_str()
可以让我的类型。
如果在一个请求没有任何反应,我怎样才能使send
还是回到有意义的事?
这是我现在的代码:
fn send<R, T>(
&self,
request: &RpcRequest<T>,
) -> Result<R, ApiError>
where
T: Serialize + Debug,
R: DeserializeOwned + Debug,
let res = serde_json::from_str(&buf).map_err(|err| ClientError::Json(err))
我现在不得不创建并返回一个Err
,但在技术上,没有返回响应该请求是预期的行为,所以我想返回比Err
以外的东西。
我试图用R
包装Option
来解决这个问题,但是这意味着我必须仔细解开每一个响应,并从reqwest响应的98%的人在他们的反应有数据,所以感觉有点像矫枉过正。
我也试图返回自制EmptyResponse
类型,但是编译器会抱怨:expected type R, found type EmptyResponse
。我想返回类型EmptyResponse
会是我想要的,但也许有人可以阐明如何可能做到这一点甚至更好一些提示。
你可以返回一个Result<Option<R>, ApiError>
如图the documentation,那么与之相匹配的是这样的:
match sender.send(request) {
Ok(Some(r)) => {
// process response
}
Ok(None) => {
// process empty response
}
Err(e) => {
// process error
}
}
// or
if let Ok(Some(r)) = sender.send(request) {
// process response
}
我试图用
R
包装Option
来解决这个问题,但是这意味着我必须仔细解开每一个响应,并从reqwest响应的98%的人在他们的反应有数据,所以感觉有点像矫枉过正。
解缠Option
是一个非常便宜的操作,没有什么可担心的。
务实的答案是有两个功能:
fn send<R, T>(&self, request: &RpcRequest<T>) -> Result<R, ApiError>
where
T: Serialize + Debug,
R: DeserializeOwned + Debug,
fn send_no_response<T>(&self, request: &RpcRequest<T>) -> Result<(), ApiError>
where
T: Serialize + Debug,
如果您的服务器恰好返回可以反序列化为类型()
的值,那么就可以避免两种功能的开销。然而,这不是JSON,最常见的格式之一的情况下:
use serde::de::DeserializeOwned; // 1.0.85
use serde_json; // 1.0.37
type Error = Box<std::error::Error>;
type Result<T, E = Error> = std::result::Result<T, E>;
fn send<R>() -> Result<R, Error>
where
R: DeserializeOwned,
{
serde_json::from_str("").map_err(Into::into)
}
fn main() {
let _r: () = send().expect("Unable to deserialize");
}
这种恐慌:
Unable to deserialize: Error("EOF while parsing a value", line: 1, column: 0)
在专业化的世界里,你可以用它和一个辅助特征,以减少回一个功能:
#![feature(specialization)]
use serde::de::DeserializeOwned; // 1.0.85
use serde_json; // 1.0.37
type Error = Box<std::error::Error>;
type Result<T, E = Error> = std::result::Result<T, E>;
type ApiResponse = &'static str;
trait FromApi: Sized {
fn convert(response: ApiResponse) -> Result<Self, Error>;
}
impl<R> FromApi for R
where
R: DeserializeOwned,
{
default fn convert(response: ApiResponse) -> Result<R, Error> {
eprintln!("deserializing the response");
serde_json::from_str(response).map_err(Into::into)
}
}
impl FromApi for () {
fn convert(_response: ApiResponse) -> Result<Self, Error> {
eprintln!("Ignoring the response");
Ok(())
}
}
fn send<R: FromApi>() -> Result<R> {
eprintln!(r#""sending" the request"#);
let api_response = "";
R::convert(api_response)
}
fn main() {
let _r: () = send().expect("Unable to deserialize");
}