mirror of https://github.com/Trivernis/bromine.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
4.1 KiB
Rust
155 lines
4.1 KiB
Rust
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;
|
|
use typemap_rev::{TypeMap, TypeMapKey};
|
|
|
|
/// A builder for the IPC server or client.
|
|
/// ```no_run
|
|
///use typemap_rev::TypeMapKey;
|
|
/// use rmp_ipc::IPCBuilder;
|
|
///
|
|
/// struct CustomKey;
|
|
///
|
|
/// impl TypeMapKey for CustomKey {
|
|
/// type Value = String;
|
|
/// }
|
|
///
|
|
///# 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(())
|
|
/// }))
|
|
/// // register a namespace
|
|
/// .namespace("namespace")
|
|
/// .on("namespace-event", |_ctx, _event| Box::pin(async move {
|
|
/// println!("Namespace event.");
|
|
/// Ok(())
|
|
/// }))
|
|
/// .build()
|
|
/// /// add context shared data
|
|
/// .insert::<CustomKey>("Hello World".to_string())
|
|
/// // can also be build_client which would return an emitter for events
|
|
/// .build_server().await.unwrap();
|
|
///# }
|
|
/// ```
|
|
pub struct IPCBuilder {
|
|
handler: EventHandler,
|
|
address: Option<String>,
|
|
namespaces: HashMap<String, Namespace>,
|
|
data: TypeMap,
|
|
}
|
|
|
|
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::<ErrorEventData>()?;
|
|
log::warn!(
|
|
"Received Error Response from Server: {} - {}",
|
|
error_data.code,
|
|
error_data.message
|
|
);
|
|
|
|
Ok(())
|
|
})
|
|
});
|
|
Self {
|
|
handler,
|
|
address: None,
|
|
namespaces: HashMap::new(),
|
|
data: TypeMap::new(),
|
|
}
|
|
}
|
|
|
|
/// Adds globally shared data
|
|
pub fn insert<K: TypeMapKey>(mut self, value: K::Value) -> Self {
|
|
self.data.insert::<K>(value);
|
|
|
|
self
|
|
}
|
|
|
|
/// Adds an event callback
|
|
pub fn on<F: 'static>(mut self, event: &str, callback: F) -> Self
|
|
where
|
|
F: for<'a> Fn(
|
|
&'a Context,
|
|
Event,
|
|
) -> Pin<Box<(dyn Future<Output = Result<()>> + Send + 'a)>>
|
|
+ Send
|
|
+ Sync,
|
|
{
|
|
self.handler.on(event, callback);
|
|
|
|
self
|
|
}
|
|
|
|
/// Adds the address to connect to
|
|
pub fn address<S: ToString>(mut self, address: S) -> Self {
|
|
self.address = Some(address.to_string());
|
|
|
|
self
|
|
}
|
|
|
|
/// Adds a namespace
|
|
pub fn namespace<S: ToString>(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,
|
|
data: self.data,
|
|
};
|
|
server.start(&self.address.unwrap()).await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Builds an ipc client
|
|
pub async fn build_client(self) -> Result<Context> {
|
|
self.validate()?;
|
|
let client = IPCClient {
|
|
namespaces: self.namespaces,
|
|
handler: self.handler,
|
|
data: self.data,
|
|
};
|
|
|
|
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(())
|
|
}
|
|
}
|
|
}
|