rust type-conversion

rust - Transformaciones idiomáticas para String, & str, Vec<u8> y &



type-conversion (1)

Un nuevo Rustáceo como yo lucha con hacer malabarismos con estos tipos: String , &str , Vec<u8> , &[u8] .

Con el tiempo, espero tener una epifanía y de repente entender por qué algunas llamadas de biblioteca usan una u otra. Hasta entonces, necesito ayuda para trazar cada transición idiomática.

Teniendo en cuenta estos tipos:

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

Creo que he descubierto esto, pero ¿son idiomáticos?

&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)

En última instancia, quiero una tabla completa de transiciones para estos tipos:

&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]


Desde &str

  • &str -> String tiene muchos métodos igualmente válidos : String::from(st) , st.to_string() , st.to_owned() .
    • Pero te sugiero que te quedes con uno de ellos dentro de un solo proyecto. La principal ventaja de String::from es que puede usarlo como un argumento para un método de map . Entonces, en lugar de x.map(|s| String::from(s)) a menudo se puede usar x.map(String::from) .
  • &str -> &[u8] se realiza mediante st.as_bytes()
  • &str -> Vec<u8> es una combinación de &str -> &[u8] -> Vec<u8> , es decir, st.as_bytes().to_owned()

De la String

  • String -> &str solo debe estar &s donde la coerción está disponible o s.as_str() donde no lo está.
  • String -> &[u8] es lo mismo que &str -> &[u8] : s.as_bytes()
  • String -> Vec<u8> tiene un método personalizado: s.into_bytes()

Desde &[u8]

  • &[u8] -> Vec<u8> se realiza mediante u.to_owned()
  • &[u8] -> &str no existe realmente, eso sería &[u8] -> Result<&str, Error> , proporcionado a través de str::from_utf8(u)
  • &[u8] -> String es la combinación de &[u8] -> Result<&str, Error> -> Result<String, Error>

Desde Vec<u8>

  • Vec<u8> -> &[u8] debe ser justo &v donde esté disponible la coerción, o as_slice donde no esté.
  • Vec<u8> -> &str es lo mismo que Vec<u8> -> &[u8] -> Result<&str, Error> es decir, str::from_utf8(&v)
  • Vec<u8> -> String no existe realmente, eso sería Vec<u8> -> Result<String, Error> través de la String::from_utf8(v)

La coerción está disponible siempre que el objetivo no sea genérico sino explícitamente escrito como &str o &[u8] respectivamente

tl; dr

&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_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_owned() &[u8] -> String | 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::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