#[cfg(all(feature = "parse-cfg", feature = "client"))]
pub mod client_configuration_file;
#[cfg(all(feature = "parse-cfg", feature = "server"))]
pub mod server_configuration_file;
#[cfg(feature = "server")]
use crate::endpoints::{Endpoint, EndpointChannel, EndpointConfig};
use crate::interfaces::{Interface, InterfaceConfig};
use crate::notifications::Key;
use crate::Error;
#[cfg(feature = "server")]
#[derive(Debug)]
pub struct ServerConfiguration {
key: Key,
interfaces: Vec<Box<dyn Interface + Send>>,
endpoints: Vec<Box<dyn Endpoint + Send>>,
}
#[cfg(feature = "server")]
impl ServerConfiguration {
pub fn new<S: AsRef<str>>(
key: S,
interfaces: Vec<Box<dyn Interface + Send>>,
endpoints: Vec<Box<dyn Endpoint + Send>>,
) -> Result<Self, Error> {
let key = Key::derive_shared_key(key);
let config = Self { key, interfaces, endpoints };
Self::validate(config)
}
pub(crate) fn endpoint_channels(&self) -> Vec<EndpointChannel> {
use crate::notifications::ValidatedNotification;
use crate::CHANNEL_BUFFER;
use tokio::sync::broadcast;
use tokio::sync::broadcast::{Receiver, Sender};
let mut endpoints = Vec::new();
for endpoint in &self.endpoints {
let (endpoint_tx, _endpoint_rx): (Sender<ValidatedNotification>, Receiver<ValidatedNotification>) =
broadcast::channel(CHANNEL_BUFFER);
let keys = endpoint.generate_keys(&self.key);
endpoints.push(EndpointChannel::from(endpoint.clone(), endpoint_tx, keys));
}
endpoints
}
pub fn key(&self) -> &Key {
&self.key
}
pub fn interfaces(&self) -> Vec<Box<dyn Interface + Send>> {
self.interfaces.clone()
}
pub fn endpoints(&self) -> &[Box<dyn Endpoint + Send>] {
&self.endpoints
}
fn validate(config: ServerConfiguration) -> Result<ServerConfiguration, Error> {
if config.interfaces.is_empty() {
return Err(Error::MissingInterface);
}
if config.endpoints.is_empty() {
return Err(Error::MissingEndpoint);
}
Ok(config)
}
}
#[cfg(all(feature = "parse-cfg", feature = "server"))]
impl TryFrom<&str> for ServerConfiguration {
type Error = Error;
fn try_from(value: &str) -> Result<Self, Self::Error> {
server_configuration_file::ServerConfigFileParser::from(value)
}
}
#[cfg(feature = "client")]
#[derive(Debug)]
pub struct ClientConfiguration {
key: Key,
interfaces: Vec<Box<dyn Interface + Send>>,
}
#[cfg(feature = "client")]
impl ClientConfiguration {
pub fn new<S: AsRef<str>>(key: S, interfaces: Vec<Box<dyn Interface + Send>>) -> Result<Self, Error> {
let key = Key::derive_shared_key(key);
let config = Self { key, interfaces };
Self::validate(config)
}
pub fn key(&self) -> &Key {
&self.key
}
pub fn interfaces(&self) -> Vec<Box<dyn Interface + Send>> {
self.interfaces.clone()
}
fn validate(config: ClientConfiguration) -> Result<ClientConfiguration, Error> {
if config.interfaces.is_empty() {
return Err(Error::MissingInterface);
}
Ok(config)
}
}
#[cfg(all(feature = "parse-cfg", feature = "client"))]
impl TryFrom<&str> for ClientConfiguration {
type Error = Error;
fn try_from(value: &str) -> Result<Self, Self::Error> {
client_configuration_file::ClientConfigFileParser::from(value)
}
}
#[cfg(all(feature = "parse-cfg", any(feature = "client", feature = "server")))]
fn collect_interfaces(
interface_configs: Vec<Box<dyn InterfaceConfig>>,
) -> Result<Vec<Box<dyn Interface + Send>>, Error> {
interface_configs.iter().map(|cfg| cfg.to_interface()).collect()
}
#[cfg(all(feature = "parse-cfg", feature = "server"))]
fn collect_endpoints(endpoint_configs: Vec<Box<dyn EndpointConfig>>) -> Result<Vec<Box<dyn Endpoint + Send>>, Error> {
endpoint_configs.iter().map(|cfg| cfg.to_endpoint()).collect()
}