rust - 如果没有要返回的内容,如何从泛型函数返回有意义的内容?
问题描述
我正在 Rust 中构建一个库,该库具有一种send
使用 reqwest 对本地 RPC 服务器执行 HTTP 请求的方法。
R
此方法在Result
where中返回泛型类型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
将是我想要的,但也许有人可以就如何更好地做到这一点提供一些提示。
解决方案
务实的答案是有两个功能:
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,
如果您的服务器恰好返回一个可以反序列化为 type 的值 ()
,那么您可以避免两个函数的开销。但是, 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");
}
推荐阅读
- mysql - 数据库触发器 - 当更新行中的字段等于三个值之一时,更新另一个表
- php - 使用正则表达式捕获评论
- php - php copy() 复制多个文件时关闭连接
- javascript - 从 S3 getObject() 中检索图像不起作用
- amazon-web-services - 为 AWS ELB 生成公有/后端密钥
- java - android上的socket.io服务器
- git - Git revert 删除我的仓库中的每个文件
- javascript - 如何使用 javascript 创建 elementor 块
- java - 将 pdf 作为静态资源从在 docker 容器中运行的 spring 应用程序提供
- angular6 - 当我在组件的提供者中添加服务时出现没有提供者错误