Manejo Eficiente de Subcadenas en Rust con Slices

Las subcadenas (slices) en Rust son tipos de datos sin propiedad que permiten referenciar secciones contiguas de colecciones sin tomar posesión de los datos originales. Este mecanismo resuelve problemas comunes relacionados con la validez de índices y sincronización de referencias.

Consideremos una implementación inicial para encontrar la primera palabra en un texto:

fn encontrar_palabra_completa(texto: &String) -> Option<usize> {
    for (posicion, caracter) in texto.char_indices() {
        if caracter.is_whitespace() {
            return Some(posicion);
        }
    }
    None
}

Este enfoque presenta riesgos de seguridad:

fn main() {
    let mut contenido = String::from("Rust es genial");
    if let Some(indice) = encontrar_palabra_completa(&contenido) {
        contenido.clear(); // Modifica el estado original
        // ¡El índice ya no es válido! Usarlo causaría comportamiento indefinido
    }
}

La solución robusta utiliza subcadeans de texto (string slices), representadas como &str. Su sintaxis sigue el patrón [inicio..fin], donde:

  • El índice inicial está incluido
  • El índice final está excluido

Ejemplos prácticos:

let mensaje = String::from("Hola Mundo");
let saludo = &mensaje[0..4];   // "Hola"
let destino = &mensaje[5..10];  // "Mundo"
let completo = &mensaje[..];    // String completo

Las subcadenas garantizan coherencia mediante referencias válidas. Reimplementemos la función usando este principio:

fn primera_palabra(texto: &str) -> &str {
    let mut longitud = 0;
    for caracter in texto.chars() {
        if caracter.is_whitespace() {
            break;
        }
        longitud += caracter.len_utf8();
    }
    &texto[..longitud]
}

Este diseño ofrece ventajas clave:

  • Funciona con literales de cadena (let literal = "Texto fijo";)
  • Acepta tanto String como &str como entrada
  • Evita problemas de índices desincronizados

La flexibilidad se evidencia en su uso:

fn main() {
    let cadena = String::from("Ejemplo práctico");
    let fragmento = primera_palabra(&cadena[..7]); // Subcadena parcial
    let completa = primera_palabra(&cadena);      // Cadena completa

    let literal = "Texto estático";
    let parte = primera_palabra(&literal[0..5]); // Funciona con literales
}

El sistema de slices no se limita a cadenas. También aplica a arreglos:

let numeros = [10, 20, 30, 40, 50];
let segmento = &numeros[1..4]; // Contiene [20, 30, 40]

Al utilizar slices, Rust garantiza que las referencias permanezcan válidas dentro de los límites definidos, evitando errores de acceso fuera de rango siempre que se respeten los límites de caracteres UTF-8.

Etiquetas: Rust slices string-slices memory-safety utf-8

Publicado el 9-23 18:28