mod content_type;
mod metadata_type;
pub mod utils;
use std::fmt::Debug;
use std::net::{SocketAddr, TcpStream, ToSocketAddrs, UdpSocket};
use crate::error::Error;
use crate::packet::Packet;
use crate::ron::{FromRon, ToRon};
pub use content_type::ContentType;
pub use metadata_type::MetaDataType;
type SendContextOption<'a, M, C> = Option<<M as MetaDataType<'a, M, C>>::SendContext>;
type SendOutputOption<'a, M, C> = Option<<C as ContentType<'a, M, C>>::SendOutput>;
type ReceiveContextOption<'a, M, C> = Option<<M as MetaDataType<'a, M, C>>::ReceiveContext>;
type ReceiveOutputOption<'a, M, C> = Option<<C as ContentType<'a, M, C>>::ReceiveOutput>;
pub trait TcpMessage<'a, M, C>
where
Self: Default,
M: MetaDataType<'a, M, C>,
C: ContentType<'a, M, C>,
{
fn destructure(self) -> (M, C, Packet);
fn build(metadata: M, content: C, end_data: Packet) -> Self;
fn send(
self,
stream: &mut TcpStream,
context: SendContextOption<'a, M, C>,
) -> Result<SendOutputOption<'a, M, C>, Error> {
let (metadata, content, end_data) = self.destructure();
let ctx = metadata.send(stream, context)?;
let output = content.send(stream, ctx)?;
end_data.send(stream)?;
Ok(output)
}
fn receive(
stream: &mut TcpStream,
context: ReceiveContextOption<'a, M, C>,
) -> Result<(Self, ReceiveOutputOption<'a, M, C>), Error> {
let (metadata, ctx) = M::receive(stream, &context)?;
let (content, end_data, output) = C::receive(stream, &metadata, ctx)?;
let message = Self::build(metadata, content, end_data);
Ok((message, output))
}
}
pub trait UdpMessage<'a>
where
Self: Default + ToRon + FromRon<'a> + TryInto<Packet> + TryFrom<Packet>,
Error: From<<Self as TryInto<Packet>>::Error> + From<<Self as TryFrom<Packet>>::Error>,
<Self as TryInto<Packet>>::Error: Into<Error> + Debug,
<Self as TryFrom<Packet>>::Error: Into<Error> + Debug,
{
fn send_to<A>(self, socket: UdpSocket, addr: A) -> Result<(), Error>
where
A: ToSocketAddrs,
{
let packet: Packet = self.try_into()?;
packet.send_to(socket, addr)?;
Ok(())
}
fn receive_from(socket: UdpSocket) -> Result<(Self, SocketAddr), Error> {
let (packet, address) = Packet::receive_from(socket)?;
let message = Self::try_from(packet)?;
Ok((message, address))
}
fn peek_from(socket: UdpSocket) -> Result<(Self, SocketAddr), Error> {
let (packet, address) = Packet::peek_from(socket)?;
let message = Self::try_from(packet)?;
Ok((message, address))
}
fn send_to_connected(self, socket: UdpSocket) -> Result<(), Error> {
let packet: Packet = self.try_into()?;
packet.send_to_connected(socket)?;
Ok(())
}
fn receive_from_connected(socket: UdpSocket) -> Result<Self, Error> {
let packet = Packet::receive_from_connected(socket).unwrap();
let message = Self::try_from(packet)?;
Ok(message)
}
fn peek_from_connected(socket: UdpSocket) -> Result<Self, Error> {
let packet = Packet::peek_from_connected(socket)?;
let message = Self::try_from(packet)?;
Ok(message)
}
}
pub trait ContextType {}
pub trait OutputType {}