use serde::{Deserialize, Serialize};
use lazy_static::lazy_static;
use std::fmt::{Debug, Display};
use std::sync::{Arc, Mutex};
use crate::bytes::Bytes;
use crate::error::{Error, ErrorKind};
use crate::message::{ContentType, ContextType, MetaDataType, OutputType, TcpMessage, UdpMessage};
use crate::packet::{Packet, PacketKind};
use crate::ron::{FromRon, ToRon};
lazy_static! {
static ref MESSAGE_SPLIT_PATTERN: Arc<Mutex<Vec<u8>>> = {
let pattern = vec![0, 0, 0, 0];
Arc::new(Mutex::new(pattern))
};
}
pub struct Context;
impl ContextType for Context {}
pub struct Output;
impl OutputType for Output {}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message<M, C> {
metadata: M,
content: C,
end_data: Packet,
}
impl<'a, M, C> Default for Message<M, C>
where
M: Default,
C: Default,
{
fn default() -> Self {
Message {
metadata: M::default(),
content: C::default(),
end_data: Packet::default(),
}
}
}
impl<M, C> Display for Message<M, C>
where
M: Serialize,
C: Serialize,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let formatted = self
.to_ron_pretty(None)
.expect("Failed to parse a Message to RON.");
write!(f, "{}", &formatted)
}
}
impl<M, C> ToRon for Message<M, C>
where
M: Serialize,
C: Serialize,
{
}
impl<'a, M, C> FromRon<'a> for Message<M, C>
where
M: Deserialize<'a>,
C: Deserialize<'a>,
{
}
impl<M, C> TryFrom<Packet> for Message<M, C>
where
M: TryFrom<Bytes>,
Error: From<<M as TryFrom<Bytes>>::Error>,
C: TryFrom<Bytes> + Default,
Error: From<<C as TryFrom<Bytes>>::Error>,
{
type Error = Error;
fn try_from(value: Packet) -> Result<Self, Self::Error> {
let pattern: Bytes = Bytes::from(Self::split_pattern()?);
let packet_content = value.content_move();
let content_split = packet_content.split_at_pat(&pattern);
let (metadata, content, end_data) = match content_split.len() {
1 => {
let mut content_split_iter = content_split.into_iter();
let metadata_bytes = content_split_iter.next().unwrap();
let metadata = M::try_from(metadata_bytes)?;
let content = C::default();
let end_data = Packet::new(PacketKind::End, Bytes::empty())?;
(metadata, content, end_data)
}
2 => {
let mut content_split_iter = content_split.into_iter();
let metadata_bytes = content_split_iter.next().unwrap();
let content_bytes = content_split_iter.next().unwrap();
let metadata = M::try_from(metadata_bytes)?;
let content = C::try_from(content_bytes)?;
let end_data = Packet::new(PacketKind::End, Bytes::empty())?;
(metadata, content, end_data)
}
3 => {
let mut content_split_iter = content_split.into_iter();
let metadata_bytes = content_split_iter.next().unwrap();
let content_bytes = content_split_iter.next().unwrap();
let end_data_bytes = content_split_iter.next().unwrap();
let metadata = M::try_from(metadata_bytes)?;
let content = C::try_from(content_bytes)?;
let end_data = Packet::try_from(end_data_bytes)?;
(metadata, content, end_data)
}
_ => {
return Err(Error::new(
ErrorKind::ParsingFailed,
Some("Packet content can not be parsed to Message.\nMore than three parts found.".to_string()))
);
}
};
Ok(Self {
metadata,
content,
end_data,
})
}
}
impl<M, C> TryFrom<Message<M, C>> for Packet
where
M: Into<Bytes>,
C: Into<Bytes>,
{
type Error = Error;
fn try_from(value: Message<M, C>) -> Result<Self, Self::Error> {
let metadata = value.metadata;
let content = value.content;
let end_data = value.end_data;
let mut metadata_bytes: Bytes = metadata.into();
let mut content_bytes: Bytes = content.into();
let mut end_data_bytes: Bytes = end_data.into();
let mut packet_content = Bytes::empty();
packet_content.append(&mut metadata_bytes);
packet_content.append(&mut Bytes::from(Message::<M, C>::split_pattern()?));
packet_content.append(&mut content_bytes);
packet_content.append(&mut Bytes::from(Message::<M, C>::split_pattern()?));
packet_content.append(&mut end_data_bytes);
Packet::new(PacketKind::Unit, packet_content)
}
}
impl<'a, M, C> TcpMessage<'a, M, C> for Message<M, C>
where
M: MetaDataType<'a, M, C> + Debug + Default,
C: ContentType<'a, M, C> + Default,
{
fn destructure(self) -> (M, C, Packet) {
let Self {
metadata,
content,
end_data,
} = self;
(metadata, content, end_data)
}
fn build(metadata: M, content: C, end_data: Packet) -> Self {
Self {
metadata,
content,
end_data,
}
}
}
impl<'a, M, C> UdpMessage<'a> for Message<M, C>
where
Self: Default + ToRon + FromRon<'a> + TryFrom<Packet> + TryInto<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,
{
}
impl<M, C> Message<M, C> {
pub fn split_pattern() -> Result<Vec<u8>, Error> {
match MESSAGE_SPLIT_PATTERN.try_lock() {
Ok(value) => Ok(value.clone()),
Err(e) => Err(Error::new(
ErrorKind::OtherSource(Box::new(e)),
Some("Failed to acquire a lock to MESSAGE_SPLIT_PATTERN.".to_string()),
)),
}
}
pub fn set_split_pattern(mut value: Vec<u8>) -> Result<(), Error> {
match MESSAGE_SPLIT_PATTERN.lock() {
Ok(mut inner) => {
inner.truncate(0);
inner.append(&mut value);
Ok(())
}
Err(e) => Err(Error::new(
ErrorKind::OtherSource(Box::new(e)),
Some("Failed to acquire a lock to MESSAGE_SPLIT_PATTERN.".to_string()),
)),
}
}
}
#[test]
fn split_pattern_test() {
let new_pat = vec![1, 2, 3, 4];
Message::<usize, usize>::set_split_pattern(new_pat).unwrap();
let pat = Message::<usize, usize>::split_pattern().unwrap();
println!("{:?}", &pat);
assert_eq!(vec![1, 2, 3, 4], pat);
}