use crate::error::{Error, Result}; use crate::events::error_event::{ErrorEventData, ERROR_EVENT_NAME}; use crate::events::event::Event; use crate::events::event_handler::EventHandler; use crate::ipc::client::IPCClient; use crate::ipc::context::Context; use crate::ipc::server::IPCServer; use crate::namespaces::builder::NamespaceBuilder; use crate::namespaces::namespace::Namespace; use std::collections::HashMap; use std::future::Future; use std::pin::Pin; #[derive(Clone)] /// A builder for the IPC server or client. /// ```no_run ///use rmp_ipc::IPCBuilder; ///# async fn a() { /// IPCBuilder::new() /// .address("127.0.0.1:2020") /// // register callback /// .on("ping", |_ctx, _event| Box::pin(async move { /// println!("Received ping event."); /// Ok(()) /// })) /// // can also be build_client which would return an emitter for events /// .build_server().await.unwrap(); ///# } /// ``` pub struct IPCBuilder { handler: EventHandler, address: Option, namespaces: HashMap, } impl IPCBuilder { pub fn new() -> Self { let mut handler = EventHandler::new(); handler.on(ERROR_EVENT_NAME, |_, event| { Box::pin(async move { let error_data = event.data::()?; log::warn!( "Received Error Response from Server: {} - {}", error_data.code, error_data.message ); Ok(()) }) }); Self { handler, address: None, namespaces: HashMap::new(), } } /// Adds an event callback pub fn on(mut self, event: &str, callback: F) -> Self where F: for<'a> Fn( &'a Context, Event, ) -> Pin> + Send + 'a)>> + Send + Sync, { self.handler.on(event, callback); self } /// Adds the address to connect to pub fn address(mut self, address: S) -> Self { self.address = Some(address.to_string()); self } /// Adds a namespace pub fn namespace(self, name: S) -> NamespaceBuilder { NamespaceBuilder::new(self, name.to_string()) } /// Adds a namespace to the ipc server pub fn add_namespace(mut self, namespace: Namespace) -> Self { self.namespaces .insert(namespace.name().to_owned(), namespace); self } /// Builds an ipc server pub async fn build_server(self) -> Result<()> { self.validate()?; let server = IPCServer { namespaces: self.namespaces, handler: self.handler, }; server.start(&self.address.unwrap()).await?; Ok(()) } /// Builds an ipc client pub async fn build_client(self) -> Result { self.validate()?; let client = IPCClient { namespaces: self.namespaces, handler: self.handler, }; let ctx = client.connect(&self.address.unwrap()).await?; Ok(ctx) } /// Validates that all required fields have been provided fn validate(&self) -> Result<()> { if self.address.is_none() { Err(Error::BuildError("Missing Address".to_string())) } else { Ok(()) } } }