paint-brush
Portales cifrados: cómo creamos una aplicación Swift que utiliza Rustpor@ockam
10,620 lecturas
10,620 lecturas

Portales cifrados: cómo creamos una aplicación Swift que utiliza Rust

por Ockam5m2024/01/01
Read on Terminal Reader

Demasiado Largo; Para Leer

Cómo la aplicación Portals para Mac, integrada en Swift, utiliza la biblioteca Ockam Rust para compartir servicios de forma privada con tus amigos a través de portales cifrados de extremo a extremo.
featured image - Portales cifrados: cómo creamos una aplicación Swift que utiliza Rust
Ockam HackerNoon profile picture
0-item
1-item

Portals es una aplicación para Mac integrada en Swift. Es de código abierto y utiliza la biblioteca Ockam Rust para compartir de forma privada servicios TCP o HTTP desde su Mac con sus amigos a través de portales Ockam cifrados de extremo a extremo. ¡Aparece un servicio compartido en su host local !


En esta publicación, profundizaremos en cómo interactúa la aplicación SwiftUI macOS con el código Rust.


Si tienes curiosidad por probar Portals para Mac. Puede obtener más información al respecto en este artículo e instalarlo utilizando Homebrew de la siguiente manera:


 brew install build-trust/ockam/portals


Aquí hay un vídeo de 2 minutos de la aplicación en acción:

Rápido <> Óxido

La funcionalidad Portales ya estaba implementada en la biblioteca Ockam Rust. Nos propusimos crear una excelente experiencia nativa de macOS.


Nuestro primer intento de crear la aplicación fue utilizando Tauri. Esto tenía sentido ya que queríamos utilizar la biblioteca de óxido de Ockam y la mayoría de las personas de nuestro equipo se sienten cómodas construyendo cosas en Rust. Esta primera versión fue fácil de construir y tenía todas las funciones básicas que queríamos. Sin embargo, la experiencia de usar la aplicación no fue muy buena. Tauri solo nos dio un control mínimo sobre cómo se representaba el menú y qué sucedía cuando un usuario interactúa con el menú. Esta versión de la aplicación parecía pertenecer a una versión de macOS de hace 10 años en comparación con los elementos de la barra de menú súper fáciles de usar integrados en macOS Sonoma.


Nos dimos cuenta de que para tener la rica experiencia que queremos, debemos crear la aplicación usando SwiftUI.


Desafortunadamente, no pudimos encontrar una solución disponible para integrar Swift y Rust que nos brindara lo mejor de ambos mundos; la seguridad de Rust y la rica experiencia nativa de macOS de SwiftUI. Después de investigar un poco más, nos dimos cuenta de que podemos conectar los dos usando C-89. Rust es compatible con la convención de llamadas de C y Swift es interoperable con Objective-C, que es un superconjunto de C-89.


Cómo se comunican Swift y Rust



Escribimos las estructuras de datos de Rust que debían ser visibles para Swift dos veces. Una versión es idiomática en Rust y fácil de usar. La otra versión es compatible con C y utiliza punteros y memoria que se asigna manualmente con malloc. También expusimos algunas API compatibles con C que utilizan punteros sin formato en Rust inseguro para convertir las estructuras de datos idiomáticas a sus versiones compatibles con C. Finalmente generamos automáticamente un encabezado C con la ayuda de la biblioteca cbindgen.


En el lado de Swift, podríamos haber llamado a las API de C directamente, pero las estructuras de datos de C no son ciudadanos de primera clase en Swift. Esto los hace más difíciles de usar idiomáticamente dentro del código SwiftUI. En su lugar, optamos por duplicar las estructuras de datos en Swift y convertirlas entre C y Swift. Esto puede parecer engorroso, pero en la práctica, el estado compartido no cambia muy a menudo. La capacidad de crear rápidamente componentes en SwiftUI utilizando construcciones como if let ... , ForEach , enum , etc. es muy útil y vale la pena el sacrificio.


Aquí hay un ejemplo de la misma estructura en sus 4 formas:


 // Rust idiomatic structure #[derive(Default, Clone, Debug, Eq, PartialEq)] pub struct LocalService { pub name: String, pub address: String, pub port: u16, pub shared_with: Vec<Invitee>, pub available: bool, } // Rust C-compatible structure #[repr(C)] pub struct LocalService { pub(super) name: *const c_char, pub(super) address: *const c_char, pub(super) port: u16, pub(super) shared_with: *const *const Invitee, pub(super) available: u8, } // Generated C header structure typedef struct C_LocalService { const char *name; const char *address; uint16_t port; const struct C_Invitee *const *shared_with; uint8_t available; } C_LocalService; // Swift idiomatic structure class LocalService { let name: String @Published var address: String? @Published var port: UInt16 @Published var sharedWith: [Invitee] @Published var available: Bool }


La aplicación Swift está vinculada estáticamente a nuestra biblioteca Rust en el momento de la compilación. El flujo de datos es simple: las interacciones de la interfaz de usuario se envían desde Swift a Rust como acciones llamando a las API de C, los eventos de cambio los emite solo Rust y se notifica a Swift mediante devoluciones de llamada que conducen a actualizaciones de la interfaz de usuario.


La mayor parte del código en las vistas de SwiftUI se parece a cualquier otra aplicación de SwiftUI.


 VStack(alignment: .leading, spacing: 0) { Text(service.sourceName).lineLimit(1) HStack(spacing: 0) { Image(systemName: "circle.fill") .font(.system(size: 7)) .foregroundColor( service.enabled ? (service.available ? .green : .red) : .orange) if !service.enabled { Text(verbatim: "Not connected") } else { if service.available { Text(verbatim: service.address.unsafelyUnwrapped + ":" + String(service.port)) } else { Text(verbatim: "Connecting") } } } ...


Si tiene curiosidad por obtener más información, consulte el código de la caja ockam_app_lib y la aplicación Portals en Swift . El Makefile en la carpeta Swift también es un buen lugar para explorar cómo se construye y vincula todo.


Si está interesado en contribuir con el código Swift o Rust de Portals para Mac , agregamos nuevos primeros números cada semana y nos encanta ayudar a los nuevos contribuyentes. Únase a nosotros en la discordia de los contribuyentes .


También aparece aquí .