use bytes::BytesMut;
use nom::multi::length_data;
use super::{
error::Error,
header::io::be_header,
r#type::{io::be_packet_type, Type},
*,
};
use crate::varint::be_varint;
fn be_payload(
pkty: Type,
datagram: &mut BytesMut,
remain_len: usize,
) -> Result<(BytesMut, usize), Error> {
let offset = datagram.len() - remain_len;
let input = &datagram[offset..];
let (remain, payload) = length_data(be_varint)(input).map_err(|e| match e {
ne @ nom::Err::Incomplete(_) => Error::IncompleteHeader(pkty, ne.to_string()),
_ => unreachable!("parsing packet header never generates error or failure"),
})?;
let payload_len = payload.len();
if payload_len < 20 {
return Err(Error::UnderSampling(payload.len()));
}
let packet_length = datagram.len() - remain.len();
let bytes = datagram.split_to(packet_length);
Ok((bytes, packet_length - payload_len))
}
pub fn be_packet(datagram: &mut BytesMut, dcid_len: usize) -> Result<Packet, Error> {
let input = datagram.as_ref();
let (remain, pkty) = be_packet_type(input).map_err(|e| match e {
ne @ nom::Err::Incomplete(_) => Error::IncompleteType(ne.to_string()),
nom::Err::Error(e) => e,
_ => unreachable!("parsing packet type never generates failure"),
})?;
let (remain, header) = be_header(pkty, dcid_len, remain).map_err(|e| match e {
ne @ nom::Err::Incomplete(_) => Error::IncompleteHeader(pkty, ne.to_string()),
_ => unreachable!("parsing packet header never generates error or failure"),
})?;
match header {
Header::VN(header) => Ok(Packet::VN(header)),
Header::Retry(header) => Ok(Packet::Retry(header)),
Header::Initial(header) => {
let (bytes, offset) = be_payload(pkty, datagram, remain.len())?;
Ok(Packet::Data(DataPacket {
header: DataHeader::Long(long::DataHeader::Initial(header)),
bytes,
offset,
}))
}
Header::ZeroRtt(header) => {
let (bytes, offset) = be_payload(pkty, datagram, remain.len())?;
Ok(Packet::Data(DataPacket {
header: DataHeader::Long(long::DataHeader::ZeroRtt(header)),
bytes,
offset,
}))
}
Header::Handshake(header) => {
let (bytes, offset) = be_payload(pkty, datagram, remain.len())?;
Ok(Packet::Data(DataPacket {
header: DataHeader::Long(long::DataHeader::Handshake(header)),
bytes,
offset,
}))
}
Header::OneRtt(header) => {
if remain.len() < 20 {
return Err(Error::UnderSampling(remain.len()));
}
let bytes = datagram.clone();
let offset = bytes.len() - remain.len();
datagram.clear();
Ok(Packet::Data(DataPacket {
header: DataHeader::Short(header),
bytes,
offset,
}))
}
}
}