【问题标题】:Using convert::Into with enum to unwrap and convert value使用 convert::Into 和枚举来解包和转换值
【发布时间】:2015-04-22 09:04:31
【问题描述】:

我开始对 Rust 感到满意,但仍有一些事情真的让我在生命周期中绊倒。在这种特殊情况下,我想要做的是有一个枚举,它可能有不同的类型包装为通用参数类,以在 URL 中创建强类型查询参数,尽管特定用例无关紧要,并返回该包装的转换将值转换为 &str。这是我想做的一个例子:

enum Param<'a> {
   MyBool(bool),
   MyLong(i64),
   MyStr(&'a str),
}

impl<'a> Param<'a> {
    fn into(self) -> (&'static str, &'a str) {
        match self {
            Param::MyBool(b) => ("my_bool", &b.to_string()), // clearly wrong
            Param::MyLong(i) => ("my_long", &i.to_string()), // clearly wrong
            Param::Value(s) => ("my_str", s),
        }
    }
}

我最终要做的是处理明显的生命周期问题(是的,我很清楚为什么生命周期对于 into() 函数来说不够长):

enum Param<'a> {
   MyBool(&'a str), // no more static typing :(
   MyLong(&'a str), // no more static typing :(
   MyStr(&'a str),
}

impl<'a> Param<'a> {
    fn into(self) -> (&'static str, &'a str) {
        match self {
            Param::MyBool(b) => ("my_bool", b),
            Param::MyLong(i) => ("my_long", i),
            Param::Value(s) => ("my_str", s),
        }
    }
}

在我真正想做的是保证某些参数的静态类型的情况下,这似乎是一个丑陋的解决方法,b/c 现在它是负责正确类型转换的枚举的构造函数。好奇是否有办法做到这一点......是的,在某些时候我需要 &str 因为这是其他地方的参数,特别是:

let body = url::form_urlencoded::serialize(
               vec![Param::MyBool(&true.to_string()).
                       into()].
                   into_iter());

我经历了一大堆事情,比如尝试从 into() 返回字符串而不是 &amp;str,但这只会导致转换问题出现在 map()String -> &amp;str。从一开始就让元组正确是最简单的事情,而不是在那之后动辄与编译器对抗。

-- 更新--

好的,所以我回到枚举的into() 函数中的(String,String) 元组。事实证明,有一个“自有”版本的 url::form_urlencoded::serialize() 函数与之兼容。

pub fn serialize_owned(pairs: &[(String, String)]) -> String

但是,现在我也在尝试对hyper::URL 中的查询字符串使用相同的模式,具体来说:

fn set_query_from_pairs<'a, I>(&mut self, pairs: I) 
    where I: Iterator<Item=(&'a str, &'a str)>

然后我尝试在 (String,String) 元组中的迭代器上使用 map()

params: Iterator<Item=(String, String)>

url.set_query_from_pairs(params.map(|x: (String, String)| -> 
    (&str, &str) { let (ref k, ref v) = x; (k, v) } ));

但这会出错:x.0 寿命不够长。在这种情况下 Ref 似乎是正确的,对吧?如果我不使用 ref,那么它的 k/v 寿命不够长。我在其中缺少一些“简单”的东西吗?

【问题讨论】:

    标签: rust hyper


    【解决方案1】:

    目前还不清楚为什么不能这样做:

    enum Param<'a> {
       MyBool(bool),
       MyLong(i64),
       MyStr(&'a str),
    }
    
    impl<'a> Param<'a> {
        fn into(self) -> (&'static str, String) {
            match self {
                Param::MyBool(b) => ("my_bool", b.to_string()),
                Param::MyLong(i) => ("my_long", i.to_string()),
                Param::MyStr(s) => ("my_str", s.into()),
            }
        }
    }
    

    into()&amp;str -&gt; String 的转换比to_string() 效率略高)

    您始终可以从String 获得&amp;str,例如使用 deref 强制或显式切片。

    【讨论】:

    • 还有std::borrow::Cow&lt;str&gt;
    • 所以问题是稍后我需要转换为 &str 以将向量传递给序列化函数。如果我在参数中使用字符串,那么我需要为 vec 解包它!被传递给序列化,此时需要迭代器上的 map() 方法。然后该地图上的函数需要从 String 移动到 &str:fn map_str_string&lt;'a&gt;(value: (&amp;'static str, String)) -&gt; (&amp;'static str, &amp;'a str) { let (k,v) = value; return (k,&amp;v); }
    • 我会将此标记为已回答,但请重新询问交互者对话问题。感谢您的帮助。
    • 仅供参考,有关迭代器 (String,String) 到 (&str, &str) 转换的问题,请参阅:stackoverflow.com/questions/29818290/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    相关资源
    最近更新 更多