use crate::codec::body::chunked_decoder::ChunkedDecoder;
use crate::codec::body::length_decoder::LengthDecoder;
use crate::protocol::{ParseError, PayloadItem, PayloadSize};
use bytes::BytesMut;
use tokio_util::codec::Decoder;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PayloadDecoder {
kind: Kind,
}
#[derive(Debug, Clone, PartialEq, Eq)]
enum Kind {
Length(LengthDecoder),
Chunked(ChunkedDecoder),
NoBody,
}
impl PayloadDecoder {
#[allow(unused)]
pub fn empty() -> Self {
Self { kind: Kind::NoBody }
}
pub fn chunked() -> Self {
Self { kind: Kind::Chunked(ChunkedDecoder::new()) }
}
#[allow(unused)]
pub fn fix_length(size: u64) -> Self {
Self { kind: Kind::Length(LengthDecoder::new(size)) }
}
#[allow(unused)]
pub fn is_chunked(&self) -> bool {
match &self.kind {
Kind::Length(_) => false,
Kind::Chunked(_) => true,
Kind::NoBody => false,
}
}
#[allow(unused)]
pub fn is_empty(&self) -> bool {
match &self.kind {
Kind::Length(_) => false,
Kind::Chunked(_) => false,
Kind::NoBody => true,
}
}
#[allow(unused)]
pub fn is_fix_length(&self) -> bool {
match &self.kind {
Kind::Length(_) => true,
Kind::Chunked(_) => false,
Kind::NoBody => false,
}
}
}
impl From<PayloadSize> for PayloadDecoder {
fn from(payload_size: PayloadSize) -> Self {
match payload_size {
PayloadSize::Length(u64) => PayloadDecoder::fix_length(u64),
PayloadSize::Chunked => PayloadDecoder::chunked(),
PayloadSize::Empty => PayloadDecoder::empty(),
}
}
}
impl Decoder for PayloadDecoder {
type Item = PayloadItem;
type Error = ParseError;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
match &mut self.kind {
Kind::Length(length_decoder) => length_decoder.decode(src),
Kind::Chunked(chunked_decoder) => chunked_decoder.decode(src),
Kind::NoBody => Ok(Some(PayloadItem::Eof)),
}
}
}