gpt4 book ai didi

types - Rust:Traits 中的通用返回类型,用于返回非对象安全 Traits 的实现

转载 作者:行者123 更新时间:2023-12-03 11:45:43 28 4
gpt4 key购买 nike

我是 Rust 的新手,我想通过实现一些小项目来学习这门语言并更好地理解。我的第一次尝试是解析从 MQTT 代理收到的 JSON 数据。
我很高兴在 tornado 的帮助下轻松完成这项工作。和 serde .然而,很快出现了一种我想(理想情况下)提取到特征中的模式。

let person_stream = sender.subscribe().filter_map(|data| {
if let Ok(value) = data {
return serde_json::from_slice::<Person>(&value).ok();
}
None
});

在哪里 sender通常是 tokio::sync::*::SenderPerson将实现 serde::de::DeserializeOwned特征。

所以我们的目标是实现一些需要 tokio::stream::StreamExt<Item = Vec<u8>> 的东西。和 transform它变成另一个 StreamExt其中关联类型 Item将实现 DeserializOwned .

我花了很长时间才弄清楚(因为我最初想使用 Trait 或带有泛型的函数),然后我想出了

fn transform<T, U, V>(stream: U) -> impl StreamExt<Item = T>
where
T: serde::de::DeserializeOwned,
U: StreamExt<Item = Result<Vec<u8>, V>>,
{
stream.filter_map(|data| {
if let Ok(value) = data {
return serde_json::from_slice::<T>(&value).ok();
}
None
})
}

虽然这行得通,但我最初想要一个像

trait Transform<T>
{
fn transform(self) -> T;
}

或实现 Into这实际上是相同的,我可以为 StreamExt<Item = Vec<u8>> 实现.由于 impl Trait返回不适用于 Traits,这是我认为我拥有的唯一选择。但是,我在实现这一点时遇到了几个问题。
  • 使用 tokio::stream::filter_map::FilterMap<_,_>对于 T (这是 filter_map() 的返回类型)是不可能的,因为模块 filter_mapprivate .
  • 使用 Box<dyn StreamExt>也不可能,因为 StreamExt返回 Self在几个功能中。不过,我一开始不希望堆开销 ;)

  • 所以我的问题是:考虑到 filter_map() 的返回类型,我可以在这里做些什么来获得 Trait 实现的语法糖吗?是 privateStreamExt不是对象安全的吗?使用会很酷

    let person_stream = receiver.transform();

    into() .显然我有一个可行的实现,所以这对我来说并不是一个真正的关键问题。但正如我一开始所说的,我想首先对 Rust 有更深入和更好的理解。

    我注意到有 tokio-serde crate,但乍一看它只处理框架数据,所以我没有深入研究它。

    PS:
    我还遇到了免费功能 transform 的问题我在类型推断失败时实现了。例如,当将新流传递给类似的函数时

    async fn debug_sink<T>(mut receiver: T)
    where
    T: StreamExt + Unpin,
    T::Item: std::fmt::Debug,
    {
    while let Some(item) = receiver.next().await {
    println!("Item: {:#?}", item);
    }
    }

    在这种情况下,它显然无法推断 Ttransfer与水槽相反

    async fn person_sink(mut receiver: impl StreamExt<Item = Person> + Unpin) {
    while let Some(person) = receiver.next().await {
    println!("Person: {:#?}", person);
    }
    }

    但是我不想注释所有类型参数,只注释它无法推断的一个。经过反复试验,我发现我可以使用

    transform::<Person, _, _>(stream);

    我完全不知道。不过,我在文档中找不到这个。这是一些隐藏的功能,还是我只是未能正确 rtfm? :)

    最佳答案

    我认为你需要的东西可以在 Nightly 的 type_alias_impl_trait 下找到。特征。基本上,它允许您在特征中编写关联类型,然后在实现中,而不是编写命名类型,使用 impl BaseTrait句法。

    我懒得用 type_alias_impl_trait 写你的代码(并且您没有提供可编译的片段)但这是一个工作示例( playground ):

    #![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!"
    }
    }

    注意 ()::do_something实际上返回一个 &'static str但从未提及这种类型。

    关于types - Rust:Traits 中的通用返回类型,用于返回非对象安全 Traits 的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61160279/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com