use crate::error::{StreamError, StreamErrorKind};
use bytes::BytesMut;
use serde::Deserialize;
use std::marker::PhantomData;
use tokio_util::codec::{Decoder, LinesCodec, LinesCodecError};
#[derive(Debug)]
pub struct JsonNewLineCodec<T> {
inner: LinesCodec,
_ph: PhantomData<fn() -> T>,
}
impl<T> JsonNewLineCodec<T> {
pub fn new_with_max_length(max_length: usize) -> Self {
Self {
inner: LinesCodec::new_with_max_length(max_length),
_ph: PhantomData,
}
}
}
fn frame_error(err: LinesCodecError) -> StreamError {
match err {
LinesCodecError::MaxLineLengthExceeded => StreamError::new(
StreamErrorKind::MaxLenReachedError,
None,
Some("Max line length reached".into()),
),
LinesCodecError::Io(err) => StreamError::from(err),
}
}
fn parse<T>(line: &str) -> Option<Result<T, StreamError>>
where
T: for<'de> Deserialize<'de>,
{
Some(
serde_json::from_str(line)
.map_err(|err| StreamError::new(StreamErrorKind::CodecError, Some(Box::new(err)), None)),
)
}
impl<T> Decoder for JsonNewLineCodec<T>
where
T: for<'de> Deserialize<'de>,
{
type Item = Result<T, StreamError>;
type Error = StreamError;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, StreamError> {
match self.inner.decode(buf).map_err(frame_error)? {
Some(line) => Ok(parse(&line)),
None => Ok(None),
}
}
fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, StreamError> {
match self.inner.decode_eof(buf).map_err(frame_error)? {
Some(line) => Ok(parse(&line)),
None => Ok(None),
}
}
}