use std::{
any::Any,
cmp::Ordering,
error::Error,
fmt,
fmt::{Debug, Display},
hash::{Hash, Hasher},
sync::Arc,
};
use crate::{
control::Direction,
id::ConnId,
io::{RxBox, TxBox},
Control, Link, Listener, Server, Task,
};
mod acceptor;
mod connector;
pub use acceptor::*;
pub use connector::*;
#[derive(Clone, Debug)]
pub struct LinkError<TAG> {
pub id: Option<ConnId>,
pub tag: TAG,
pub error: Arc<std::io::Error>,
}
impl<TAG> LinkError<TAG>
where
TAG: Clone,
{
pub fn outgoing(id: ConnId, tag: &TAG, error: std::io::Error) -> Self {
Self { id: Some(id), tag: tag.clone(), error: Arc::new(error) }
}
pub fn incoming(tag: &TAG, error: std::io::Error) -> Self {
Self { id: None, tag: tag.clone(), error: Arc::new(error) }
}
pub fn direction(&self) -> Direction {
if self.id.is_some() {
Direction::Outgoing
} else {
Direction::Incoming
}
}
}
impl<TAG> fmt::Display for LinkError<TAG>
where
TAG: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {}", &self.tag, &self.error)
}
}
impl<TAG> Error for LinkError<TAG> where TAG: fmt::Display + fmt::Debug {}
pub trait LinkTag: Debug + Display + Send + Sync + 'static {
fn transport_name(&self) -> &str;
fn direction(&self) -> Direction;
fn user_data(&self) -> Vec<u8>;
fn as_any(&self) -> &dyn Any;
fn box_clone(&self) -> LinkTagBox;
fn dyn_cmp(&self, other: &dyn LinkTag) -> Ordering;
fn dyn_hash(&self, state: &mut dyn Hasher);
}
impl PartialEq for dyn LinkTag {
fn eq(&self, other: &Self) -> bool {
self.cmp(other).is_eq()
}
}
impl Eq for dyn LinkTag {}
impl PartialOrd for dyn LinkTag {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(Ord::cmp(self, other))
}
}
impl Ord for dyn LinkTag {
fn cmp(&self, other: &Self) -> Ordering {
let id = self.as_any().type_id();
let other_id = other.as_any().type_id();
self.transport_name()
.cmp(other.transport_name())
.then(id.cmp(&other_id).then_with(|| self.dyn_cmp(other)))
}
}
impl Hash for dyn LinkTag {
fn hash<H: Hasher>(&self, state: &mut H) {
let id = self.as_any().type_id();
id.hash(state);
self.dyn_hash(state);
}
}
pub type LinkTagBox = Box<dyn LinkTag>;
impl Clone for LinkTagBox {
fn clone(&self) -> Self {
self.box_clone()
}
}
pub type BoxControl = Control<TxBox, RxBox, LinkTagBox>;
pub type BoxServer = Server<TxBox, RxBox, LinkTagBox>;
pub type BoxListener = Listener<TxBox, RxBox, LinkTagBox>;
pub type BoxTask = Task<TxBox, RxBox, LinkTagBox>;
pub type BoxLink = Link<LinkTagBox>;
pub type BoxLinkError = LinkError<LinkTagBox>;