Slice como array en Rust: por qué es difícil y cómo hacerlo correctamente
\n\nCualquiera que haya escrito en Rust más de un par de días se ha encontrado con una situación frustrante: tienes un &[u8] (slice), pero la función necesita un [u8; 4] (array). En C, simplemente tomarías un puntero. En Python, harías un slice. En Rust... comienza el baile. Pero no te asustes: detrás de esta complejidad hay una seguridad brillante.
En este artículo, analizaremos cómo obtener un slice como array en Rust de todas las formas posibles: desde "rápido y sucio" hasta "correcto y confiable". Aprenderás por qué Rust no permite simplemente convertir un slice en un array y cómo sortear este "problema" con el máximo rendimiento.
\n\n¿Por qué Rust no permite simplemente copiar un slice a un array?
\n\nImagina que pides una pizza y te traen una rebanada. Dices: "Esto es parte de la pizza, hazla entera". Lo mismo ocurre con un slice: es una referencia a una parte de los datos, mientras que un array es un tipo propietario de longitud fija. El tamaño del array se conoce en tiempo de compilación, pero el tamaño del slice solo se conoce en tiempo de ejecución.
\n\nPor lo tanto, no puedes simplemente escribir let arr: [u8; 4] = slice. El compilador dirá: "Lo siento, no sé si tu slice cabe en un array de 4 elementos". Rust prioriza la seguridad por encima de todo: si el slice es más corto, obtendrás basura o un pánico.
Método 1: try_into() — el método moderno y seguro
\n\nA partir de Rust 1.47, apareció una forma elegante a través del trait TryInto. Este es el método recomendado para convertir un slice en un array. Devuelve un Result, por lo que siempre sabrás si la conversión fue exitosa.
use std::convert::TryInto;\n\nfn main() {\n let slice: &[u8] = &[10, 20, 30, 40, 50];\n \n // Intentamos obtener un array de 3 elementos\n let result: Result<[u8; 3], _> = slice[..3].try_into();\n \n match result {\n Ok(arr) => println!("Array: {:?}", arr),\n Err(_) => println!("¡No hay suficientes elementos!"),\n }\n \n // O simplemente usamos unwrap si estamos seguros\n let arr: [u8; 4] = slice[..4].try_into().unwrap();\n println!("Array de 4: {:?}", arr);\n}\n\n¿Cómo funciona? El método try_into() verifica la longitud del slice en tiempo de ejecución. Si la longitud coincide, lo convierte; si no, devuelve un error. Esta es la solución ideal para el 99% de los casos.
Método 2: copy_from_slice() — para quienes aman el control
\n\nSi ya tienes un array (por ejemplo, inicializado con ceros), puedes copiar los datos del slice. Este método requiere que el slice no sea más corto que el array; de lo contrario, habrá un pánico.
\n\nfn main() {\n let slice: &[u32] = &[100, 200, 300];\n let mut arr: [u32; 3] = [0; 3]; // creamos un array vacío\n \n arr.copy_from_slice(slice);\n println!("Copiado: {:?}", arr);\n \n // Si el slice es más largo, toma un subconjunto\n let long_slice = &[1, 2, 3, 4, 5];\n let mut small_arr = [0u8; 2];\n small_arr.copy_from_slice(&long_slice[..2]);\n println!("Parte del slice: {:?}", small_arr);\n}\n\nImportante: copy_from_slice solo funciona para tipos que implementan Copy (por ejemplo, números). Para cadenas, debes usar clone_from_slice.
Método 3: Iteración manual — para extremos
\n\nA veces necesitas hacer algo no estándar. Por ejemplo, convertir un slice cambiando el orden o filtrando. Entonces puedes iterar manualmente:
\n\nfn slice_to_array<T: Copy, const N: usize>(slice: &[T]) -> Option<[T; N]> {\n if slice.len() != N {\n return None;\n }\n \n let mut arr = [unsafe { std::mem::zeroed() }; N];\n for (i, &val) in slice.iter().enumerate() {\n arr[i] = val;\n }\n Some(arr)\n}\n\nfn main() {\n