使用 convert::Into 和枚举来解包和转换值
Using convert::Into with enum to unwrap and convert value
我开始对 Rust 感到满意,但仍然有一些事情让我终生困扰。在这种特殊情况下,我想要做的是有一个枚举,它可能将不同类型包装为通用参数 class,以在 URL 中创建强类型查询参数,尽管具体用例无关紧要, 和 return 将该包装值转换为 &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());
我经历了一大堆事情,比如尝试 return String 而不是 into()
中的 &str
,但这只会导致 [=19] 的转换问题=] String
-> &str
。从一开始就让元组正确是最简单的事情,而不是在那之后每次都与编译器作对。
--更新--
好的,所以我回到枚举的 into()
函数中的 (String,String)
元组。事实证明,url::form_urlencoded::serialize()
函数有一个 "owned" 版本与之兼容。
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 活得不够长。我在这里面遗漏了什么 'simple' 吗?
不太清楚为什么你不能这样做:
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()
for &str -> String
的转换效率略高于 to_string()
)
您总是可以从 String
得到一个 &str
,例如使用 deref 强制或显式切片。
我开始对 Rust 感到满意,但仍然有一些事情让我终生困扰。在这种特殊情况下,我想要做的是有一个枚举,它可能将不同类型包装为通用参数 class,以在 URL 中创建强类型查询参数,尽管具体用例无关紧要, 和 return 将该包装值转换为 &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());
我经历了一大堆事情,比如尝试 return String 而不是 into()
中的 &str
,但这只会导致 [=19] 的转换问题=] String
-> &str
。从一开始就让元组正确是最简单的事情,而不是在那之后每次都与编译器作对。
--更新--
好的,所以我回到枚举的 into()
函数中的 (String,String)
元组。事实证明,url::form_urlencoded::serialize()
函数有一个 "owned" 版本与之兼容。
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 活得不够长。我在这里面遗漏了什么 'simple' 吗?
不太清楚为什么你不能这样做:
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()
for &str -> String
的转换效率略高于 to_string()
)
您总是可以从 String
得到一个 &str
,例如使用 deref 强制或显式切片。