Construcción y Manipulación Dinámica de Rutas de Archivo con OsStr en Rust

En el desarrollo con Rust, la manipulación de rutas y nombres de archivo requiere un manejo cuidadoso de las cadenas de texto nativas del sistema operativo. Las estructuras OsString y &OsStr están diseñadas específicamente para representar estas cadenas de manera agnóstica a la plataforma.

  • En entornos Unix, estas cadenas se almacenan como secuencias de valores de 8 bits distintos de cero, compatibles con la codificación UTF-8.
  • En sistemas Windows, se almacenan como secuencias de valores de 16 bits distintos de cero, utilizando la codificación UTF-16.

Al implementar funcionalidades como la generación de copias de seguridad o la carga de archivos adjuntos, es común necesitar ensamblar nombres de archivo de forma dinámica. A continuación, se muestra cómo lograr esto utilizando operaciones de concatenación sobre arreglos.

Enasmblaje Dinámico de Nombres de Archivo

#[cfg(test)]
mod tests {
    use std::ffi::{OsStr, OsString};

    #[test]
    fn construir_nombre_archivo_dinamico() {
        let parte_id = OsStr::new("doc");
        let parte_fecha = OsStr::new("_20231027");
        let parte_usuario = OsStr::new("_admin");
        let extension = OsStr::new(".pdf");
        
        let componentes = [parte_id, parte_fecha, parte_usuario, extension];
        let nombre_final: OsString = componentes.join(OsStr::new(""));
        
        assert_eq!(nombre_final, OsStr::new("doc_20231027_admin.pdf"));
    }
}

Análisis y Manipulación de Rutas en Windows

En entornos Windows, a menudo es necesario extraer información específica de un nombre de archivo y reestructurarlo. Esto implica trabajar directamente con la codiifcación UTF-16 subyacente mediante las extensiones del sistema operativo.

#[cfg(test)]
#[cfg(windows)]
mod windows_tests {
    use std::ffi::{OsStr, OsString};
    use std::os::windows::ffi::{OsStrExt, OsStringExt};

    #[test]
    fn procesar_y_dividir_nombre_en_windows() {
        // Conversión a secuencia UTF-16
        let nombre_base = OsStr::new("reporte_final");
        let codificacion_utf16: Vec<u16> = nombre_base.encode_wide().collect();
        
        // Verificación de la codificación UTF-16
        let esperado_utf16: Vec<u16> = "reporte_final".encode_utf16().collect();
        assert_eq!(codificacion_utf16, esperado_utf16);

        // División utilizando split_off para separar y mutar el vector original
        let mut utf16_mutable: Vec<u16> = nombre_base.encode_wide().collect();
        let parte_derecha = utf16_mutable.split_off(7);
        
        assert_eq!(utf16_mutable, "reporte".encode_utf16().collect::<vec>>());
        assert_eq!(parte_derecha, "_final".encode_utf16().collect::<vec>>());

        // División utilizando split_at para obtener vistas inmutables
        let bytes_completos: Vec<u16> = nombre_base.encode_wide().collect();
        let (prefijo, sufijo) = bytes_completos.split_at(7);
        
        assert_eq!(prefijo, "reporte".encode_utf16().collect::<vec>>().as_slice());
        assert_eq!(sufijo, "_final".encode_utf16().collect::<vec>>().as_slice());

        // Uso de splitn para dividir por un delimitador específico (ej. guion bajo)
        let nombre_complejo = OsStr::new("logs_servidor_2023_octubre");
        let bytes_utf16: Vec<u16> = nombre_complejo.encode_wide().collect();
        
        let segmentos: Vec<&[u16]> = bytes_utf16
            .splitn(4, |&codigo| codigo == '_' as u16)
            .collect();
            
        assert_eq!(segmentos.len(), 4);
        
        // Reconstrucción de una sección específica (ej. el año) a OsString
        let anio_os_string = OsString::from_wide(segmentos[2]);
        assert_eq!(anio_os_string.into_string().unwrap(), "2023");
    }
}
</u16></vec></vec></u16></vec></vec></u16></u16></u16>

Etiquetas: Rust osstring osstr utf-16 windows-ffi

Publicado el 10-27 13:58