use super::super::varint::QuicVarInt;
use super::parse::{QuicFrameField, QuicFrameParseError};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QuicNewTokenFrame<'a> {
bytes: &'a [u8],
frame_type: QuicVarInt<'a>,
token_length: QuicVarInt<'a>,
token: &'a [u8],
}
impl<'a> QuicNewTokenFrame<'a> {
pub const fn as_bytes(self) -> &'a [u8] {
self.bytes
}
pub const fn frame_type(self) -> QuicVarInt<'a> {
self.frame_type
}
pub const fn token_length(self) -> QuicVarInt<'a> {
self.token_length
}
pub const fn token(self) -> &'a [u8] {
self.token
}
}
pub(super) fn parse_new_token<'a>(
bytes: &'a [u8],
frame_type: QuicVarInt<'a>,
offset: usize,
) -> Result<(QuicNewTokenFrame<'a>, &'a [u8]), QuicFrameParseError> {
let frame_type_len = frame_type.byte_len();
let token_length_offset = offset + frame_type_len;
let token_length = QuicVarInt::parse(&bytes[frame_type_len..]).map_err(|error| {
QuicFrameParseError::Field {
field: QuicFrameField::TokenLength,
offset: token_length_offset,
error,
}
})?;
let token_length_value = token_length.value();
let token_length_usize = usize::try_from(token_length_value).map_err(|_| {
QuicFrameParseError::LengthNotRepresentable {
field: QuicFrameField::TokenLength,
offset: token_length_offset,
value: token_length_value,
}
})?;
let token_start = frame_type_len + token_length.byte_len();
let token_offset = token_length_offset + token_length.byte_len();
if token_length_usize == 0 {
return Err(QuicFrameParseError::EmptyField {
field: QuicFrameField::Token,
offset: token_offset,
});
}
let token_end =
token_start
.checked_add(token_length_usize)
.ok_or(QuicFrameParseError::LengthOverflow {
field: QuicFrameField::Token,
offset: token_offset,
length: token_length_usize,
})?;
let available = bytes.len() - token_start;
if available < token_length_usize {
return Err(QuicFrameParseError::IncompleteBytes {
field: QuicFrameField::Token,
offset: token_offset,
required: token_length_usize,
available,
});
}
Ok((
QuicNewTokenFrame {
bytes: &bytes[..token_end],
frame_type,
token_length,
token: &bytes[token_start..token_end],
},
&bytes[token_end..],
))
}