如何在 String,& str,Vec < u8 > 和 & [ u8]之间进行转换?

一个像我这样的新的甲壳类动物挣扎于这些类型的杂耍: String&strVec<u8>&[u8]

随着时间的推移,我希望有一个顿悟,并突然明白为什么一些库调用使用其中之一。在那之前,我需要有人帮我规划每个惯用转换。

鉴于这些类型:

let st: &str = ...;
let s:  String = ...;
let u:  &[u8] = ...;
let v:  Vec<u8> = ...;

我想我已经弄明白这些了,但是它们是不是成语呢?

&str    -> String    String::from(st)
&str    -> &[u8]     st.as_bytes()
String  -> &str      s.as_str()
&[u8]   -> &str      str::from_utf8(u)
Vec<u8> -> String    String::from_utf8(v)

最后,我想要一个这些类型的完整过渡表:

&str    -> String
&str    -> &[u8]
&str    -> Vec<u8>
String  -> &str
String  -> &[u8]
String  -> Vec<u8>
&[u8]   -> &str
&[u8]   -> String
&[u8]   -> Vec<u8>
Vec<u8> -> &str
Vec<u8> -> String
Vec<u8> -> &[u8]
20532 次浏览

来自 &str

  • &str -> String许多同样有效的方法: String::from(st)st.to_string()st.to_owned()
    • 但我建议你在一个项目中坚持其中一个。String::from的主要优点是可以将其用作 map方法的参数。因此,你可以经常使用 x.map(String::from)来代替 x.map(|s| String::from(s))
  • &str-> &[u8]st.as_bytes()完成
  • &str-> Vec<u8>&str -> &[u8] -> Vec<u8>的组合,即 st.as_bytes().to_vec()st.as_bytes().to_owned()

来自 String

  • String -> &str应该只是有胁迫的 &s或者没有胁迫的 s.as_str()
  • String -> &[u8]&str -> &[u8]: s.as_bytes()相同
  • String -> Vec<u8>有一个自定义方法: s.into_bytes()

来自 &[u8]

  • &[u8] -> Vec<u8>是由 u.to_owned()u.to_vec()完成的。它们做同样的事情,但是 to_vec有一个小小的优势,那就是对它返回的类型没有歧义。
  • &[u8] -> &str实际上并不存在,那就是通过 str::from_utf8(u)提供的 &[u8] -> Result<&str, Error>
    • str::from_utf8(u).unwrap()可以工作,但是您应该更喜欢更好的错误处理(参见 错误处理-结果类型)。
  • &[u8] -> String&[u8] -> Result<&str, Error> -> Result<String, Error>的组合

来自 Vec<u8>

  • Vec<u8> -> &[u8]应该只是有胁迫可用的 &v,或者没有胁迫的 as_slice
  • Vec<u8> -> &strVec<u8> -> &[u8] -> Result<&str, Error>相同,即 str::from_utf8(&v)
  • Vec<u8> -> String实际上并不存在,那就是通过 String::from_utf8(v)Vec<u8> -> Result<String, Error>

只要目标不是泛型的,而是分别显式类型为 &str&[u8]的,就可以使用强制。Rustonomicon 有一章是关于 胁迫的,里面有更多关于胁迫网站的细节。


博士

&str    -> String  | String::from(s) or s.to_string() or s.to_owned()
&str    -> &[u8]   | s.as_bytes()
&str    -> Vec<u8> | s.as_bytes().to_vec() or s.as_bytes().to_owned()
String  -> &str    | &s if possible* else s.as_str()
String  -> &[u8]   | s.as_bytes()
String  -> Vec<u8> | s.into_bytes()
&[u8]   -> &str    | s.to_vec() or s.to_owned()
&[u8]   -> String  | std::str::from_utf8(s).unwrap(), but don't**
&[u8]   -> Vec<u8> | String::from_utf8(s).unwrap(), but don't**
Vec<u8> -> &str    | &s if possible* else s.as_slice()
Vec<u8> -> String  | std::str::from_utf8(&s).unwrap(), but don't**
Vec<u8> -> &[u8]   | String::from_utf8(s).unwrap(), but don't**


* target should have explicit type (i.e., checker can't infer that)


** handle the error properly instead