Types Rust:返回非对象安全特性的实现的特性中的通用返回类型
我是个新手,我想通过实施一些小项目来学习这门语言并获得更好的理解。我的第一次尝试是解析从MQTT代理接收的JSON数据。 我很高兴在Types Rust:返回非对象安全特性的实现的特性中的通用返回类型,types,rust,serde,return-type-deduction,tokio,Types,Rust,Serde,Return Type Deduction,Tokio,我是个新手,我想通过实施一些小项目来学习这门语言并获得更好的理解。我的第一次尝试是解析从MQTT代理接收的JSON数据。 我很高兴在tornado和serde的帮助下很容易做到这一点。然而,很快就出现了一种模式,我想(理想地)将其提取成一种特征 let person_stream=sender.subscribe().filter_map(|数据|{ 如果让Ok(值)=数据{ 返回serde_json::from_slice::(&value).ok(); } 没有一个 }); 其中sende
tornado
和serde
的帮助下很容易做到这一点。然而,很快就出现了一种模式,我想(理想地)将其提取成一种特征
let person_stream=sender.subscribe().filter_map(|数据|{
如果让Ok(值)=数据{
返回serde_json::from_slice::(&value).ok();
}
没有一个
});
其中sender
通常是tokio::sync::*::sender
和Person
将实现serde::de::DeserializeOwned
特征
因此,我们的目标是实现一个将tokio::stream::StreamExt
转换为另一个StreamExt
的东西,其中关联的项将实现反序列化
我花了相当长的时间才弄明白(因为我最初想在泛型中使用特征或函数),然后我想出了
fn变换(流:U)->impl-streamxt
哪里
T:serde::de::反序列化拥有,
U:,
{
stream.filter|map(|数据|{
如果让Ok(值)=数据{
返回serde_json::from_slice::(&value).ok();
}
没有一个
})
}
虽然这是可行的,但我最初想要的是
trait变换
{
fn变换(自)->T;
}
或者将实现为
,这实际上是相同的,我可以为StreamExt
实现。由于impl Trait
return对Traits不可用,因此这是我认为唯一的选择。然而,在实现这一点时,我面临着几个问题
对于T
(这是filter\u-map()
的返回类型),无法使用tokio::stream::filter\u-map::filter\u-map
),因为模块filter\u-map
是私有的
使用Box
也不可能,因为StreamExt
在几个函数中返回Self
。不过,我一开始不希望堆开销;)李>
所以我的问题是:如果filter\u map()
的返回类型是private
并且StreamExt
不是对象安全的,那么我在这里可以做些什么来获得Trait实现的语法糖呢?使用它会很酷
let person_stream=receiver.transform();
或into()
。显然,我有一个有效的实现,所以这对我来说并不是一个真正关键的问题。但正如我一开始所说的,我首先想对锈病有一个更深入、更好的了解
我注意到有tokio serde
板条箱,但乍一看它只处理框架数据,所以我没有深入研究
附言:
当类型推断失败时,我实现的自由函数transform
I也遇到了一个问题。例如,当将新流传递给函数
async-fn-debug\u接收器(mut-receiver:T)
哪里
T:streamxt+Unpin,
T::Item:std::fmt::Debug,
{
而让一些(项目)=receiver.next().等待{
println!(“项目:{:#?}”,项目);
}
}
在这种情况下,它显然无法在transfer
中推断t
,而不是像这样
异步fn个人接收器(mut接收器:impl-streamxt+Unpin){
而让一些(人)=接收者。下一步()等待{
println!(“Person:{:#?}”,Person);
}
}
但是,我不想注释所有类型参数,只注释它无法推断的类型参数。经过反复试验,我发现我可以使用
transform::(流);
我完全不知道。不过,我在文档中找不到这个。这是某种隐藏的功能,还是我只是无法正确rtfm?:) 我认为您需要的东西可以在夜间使用type\u alias\u impl\u trait
功能。基本上,它允许您在trait中编写关联的类型,然后在实现中,使用impl BaseTrait
语法而不是编写命名类型
我懒得用type\u alias\u impl\u trait
编写代码(而且您没有提供可编译的代码段),但这里是一个工作示例():
注意()::dou_something
实际上返回了一个&'static str
,但是从来没有提到过这种类型。谢谢!这似乎就是我要找的。然而,我无法让它满足我的要求。您可能想看看这个示例。@BeneSim:我认为您的代码基本上是正确的。可能应该是type Output=impl-StreamExt代码>,或者可能不需要该注释。但是请注意,在需要错误类型注释之后,您会得到一个内部编译器错误
。这个特性仍然不稳定是有原因的……我确实用typeoutput=impl-StreamExt尝试过它代码>但它也不起作用。我猜你是对的,rustc
crash应该给我一个暗示,这个特性还没有我想要的那么稳定。也许我只是在等待,直到事情变得不稳定甚至稳定。在此之前,我将使用free函数transform
。
#![feature(type_alias_impl_trait)]
use std::fmt::Debug;
trait Foo {
type Output: Debug;
fn do_something() -> Self::Output;
}
impl Foo for () {
type Output = impl Debug;
fn do_something() -> Self::Output {
"hello!"
}
}