use bytes::BytesMut;
use tokio_util::codec::{Decoder, Encoder, LinesCodec};
use super::errors::IrcError;
use super::message::Message;
#[derive(Default)]
pub struct IrcCodec {
inner: LinesCodec,
}
impl IrcCodec {
pub(crate) fn sanitize(mut data: String) -> String {
if let Some((pos, len)) = ["\r\n", "\r", "\n"]
.iter()
.flat_map(|needle| data.find(needle).map(|pos| (pos, needle.len())))
.min_by_key(|&(pos, _)| pos)
{
data.truncate(pos + len);
}
data
}
}
impl Decoder for IrcCodec {
type Item = Message;
type Error = IrcError;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Message>, Self::Error> {
let result = self
.inner
.decode(src)
.map_err(IrcError::from)
.and_then(|res| res.map_or(Ok(None), |msg| msg.parse::<Message>().map(Some)));
println!(" << {:?}", result);
result
}
}
impl Encoder for IrcCodec {
type Item = Message;
type Error = IrcError;
fn encode(&mut self, msg: Message, dst: &mut BytesMut) -> Result<(), Self::Error> {
println!(">> {:?}", msg);
self.inner
.encode(IrcCodec::sanitize(msg.to_string()), dst)
.map_err(IrcError::from)
}
}