use crate::http3::codepoints::Http3FrameType;
use crate::http3::ids::Http3PushId;
use crate::quic::varint::{QuicVarInt, QuicVarIntLen};
use super::envelope::Http3Frame;
use super::payload::{
Http3FramePayloadBuildError, Http3FramePayloadField, Http3FramePayloadParseError, add_payload,
encode_varint, envelope, parse_exact_varint, parse_payload_varint, validate_type,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Http3CancelPush<'a> {
frame: Http3Frame<'a>,
push_id: QuicVarInt<'a>,
}
impl<'a> Http3CancelPush<'a> {
pub(in crate::http3) fn from_validated(
frame: Http3Frame<'a>,
push_id: Http3PushId,
push_id_length: QuicVarIntLen,
) -> Self {
let push_id = QuicVarInt::from_validated(
&frame.payload()[..push_id_length.byte_len()],
push_id.value(),
push_id_length,
);
Self { frame, push_id }
}
pub fn parse(
bytes: &'a [u8],
maximum_payload: usize,
) -> Result<Self, Http3FramePayloadParseError> {
Self::from_frame(
Http3Frame::parse(bytes, maximum_payload)
.map_err(Http3FramePayloadParseError::Frame)?,
)
}
pub fn from_frame(frame: Http3Frame<'a>) -> Result<Self, Http3FramePayloadParseError> {
validate_type(frame, Http3FrameType::CANCEL_PUSH)?;
let push_id = parse_exact_varint(frame.payload(), Http3FramePayloadField::PushId)?;
Ok(Self { frame, push_id })
}
pub const fn frame(&self) -> Http3Frame<'a> {
self.frame
}
pub const fn as_bytes(&self) -> &'a [u8] {
self.frame.as_bytes()
}
pub const fn push_id(&self) -> Http3PushId {
Http3PushId::new(self.push_id.value())
}
pub const fn push_id_varint(&self) -> QuicVarInt<'a> {
self.push_id
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Http3PushPromise<'a> {
frame: Http3Frame<'a>,
push_id: QuicVarInt<'a>,
}
impl<'a> Http3PushPromise<'a> {
pub(in crate::http3) fn from_validated(
frame: Http3Frame<'a>,
push_id: Http3PushId,
push_id_length: QuicVarIntLen,
) -> Self {
let push_id = QuicVarInt::from_validated(
&frame.payload()[..push_id_length.byte_len()],
push_id.value(),
push_id_length,
);
Self { frame, push_id }
}
pub fn parse(
bytes: &'a [u8],
maximum_payload: usize,
) -> Result<Self, Http3FramePayloadParseError> {
Self::from_frame(
Http3Frame::parse(bytes, maximum_payload)
.map_err(Http3FramePayloadParseError::Frame)?,
)
}
pub fn from_frame(frame: Http3Frame<'a>) -> Result<Self, Http3FramePayloadParseError> {
validate_type(frame, Http3FrameType::PUSH_PROMISE)?;
let push_id = parse_payload_varint(frame.payload(), Http3FramePayloadField::PushId, 0)?;
Ok(Self { frame, push_id })
}
pub const fn frame(&self) -> Http3Frame<'a> {
self.frame
}
pub const fn as_bytes(&self) -> &'a [u8] {
self.frame.as_bytes()
}
pub const fn push_id(&self) -> Http3PushId {
Http3PushId::new(self.push_id.value())
}
pub const fn push_id_varint(&self) -> QuicVarInt<'a> {
self.push_id
}
pub fn encoded_field_section(&self) -> &'a [u8] {
&self.frame.payload()[self.push_id.byte_len()..]
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Http3MaxPushId<'a> {
frame: Http3Frame<'a>,
push_id: QuicVarInt<'a>,
}
impl<'a> Http3MaxPushId<'a> {
pub(in crate::http3) fn from_validated(
frame: Http3Frame<'a>,
push_id: Http3PushId,
push_id_length: QuicVarIntLen,
) -> Self {
let push_id = QuicVarInt::from_validated(
&frame.payload()[..push_id_length.byte_len()],
push_id.value(),
push_id_length,
);
Self { frame, push_id }
}
pub fn parse(
bytes: &'a [u8],
maximum_payload: usize,
) -> Result<Self, Http3FramePayloadParseError> {
Self::from_frame(
Http3Frame::parse(bytes, maximum_payload)
.map_err(Http3FramePayloadParseError::Frame)?,
)
}
pub fn from_frame(frame: Http3Frame<'a>) -> Result<Self, Http3FramePayloadParseError> {
validate_type(frame, Http3FrameType::MAX_PUSH_ID)?;
let push_id = parse_exact_varint(frame.payload(), Http3FramePayloadField::PushId)?;
Ok(Self { frame, push_id })
}
pub const fn frame(&self) -> Http3Frame<'a> {
self.frame
}
pub const fn as_bytes(&self) -> &'a [u8] {
self.frame.as_bytes()
}
pub const fn push_id(&self) -> Http3PushId {
Http3PushId::new(self.push_id.value())
}
pub const fn push_id_varint(&self) -> QuicVarInt<'a> {
self.push_id
}
}
pub struct Http3CancelPushBuilder<'output> {
destination: &'output mut [u8],
push_id: Http3PushId,
}
impl<'output> Http3CancelPushBuilder<'output> {
pub fn new(destination: &'output mut [u8], push_id: Http3PushId) -> Self {
Self {
destination,
push_id,
}
}
pub fn build(self) -> Result<Http3CancelPush<'output>, Http3FramePayloadBuildError> {
let push_id = encode_varint(self.push_id.value()).map_err(|error| {
Http3FramePayloadBuildError::PayloadVarInt {
field: Http3FramePayloadField::PushId,
error,
}
})?;
let plan = envelope(
Http3FrameType::CANCEL_PUSH,
push_id.byte_len(),
self.destination,
)?;
let header_length = plan.header_length();
let required = plan.required();
let bytes = &mut self.destination[..required];
plan.write_header(bytes);
bytes[header_length..].copy_from_slice(push_id.bytes());
let frame = plan.finish(bytes);
Ok(Http3CancelPush::from_validated(
frame,
self.push_id,
push_id.len,
))
}
}
pub struct Http3PushPromiseBuilder<'output, 'section> {
destination: &'output mut [u8],
push_id: Http3PushId,
encoded_field_section: &'section [u8],
}
impl<'output, 'section> Http3PushPromiseBuilder<'output, 'section> {
pub fn new(
destination: &'output mut [u8],
push_id: Http3PushId,
encoded_field_section: &'section [u8],
) -> Self {
Self {
destination,
push_id,
encoded_field_section,
}
}
pub fn build(self) -> Result<Http3PushPromise<'output>, Http3FramePayloadBuildError> {
let push_id = encode_varint(self.push_id.value()).map_err(|error| {
Http3FramePayloadBuildError::PayloadVarInt {
field: Http3FramePayloadField::PushId,
error,
}
})?;
let payload_length = add_payload(push_id.byte_len(), self.encoded_field_section.len())
.ok_or(Http3FramePayloadBuildError::PayloadLengthOverflow {
current: push_id.byte_len(),
addition: self.encoded_field_section.len(),
})?;
let plan = envelope(
Http3FrameType::PUSH_PROMISE,
payload_length,
self.destination,
)?;
let header_length = plan.header_length();
let required = plan.required();
let bytes = &mut self.destination[..required];
plan.write_header(bytes);
let payload = &mut bytes[header_length..];
let push_id_length = push_id.byte_len();
payload[..push_id_length].copy_from_slice(push_id.bytes());
payload[push_id_length..].copy_from_slice(self.encoded_field_section);
let frame = plan.finish(bytes);
Ok(Http3PushPromise::from_validated(
frame,
self.push_id,
push_id.len,
))
}
}
pub struct Http3MaxPushIdBuilder<'output> {
destination: &'output mut [u8],
push_id: Http3PushId,
}
impl<'output> Http3MaxPushIdBuilder<'output> {
pub fn new(destination: &'output mut [u8], push_id: Http3PushId) -> Self {
Self {
destination,
push_id,
}
}
pub fn build(self) -> Result<Http3MaxPushId<'output>, Http3FramePayloadBuildError> {
let push_id = encode_varint(self.push_id.value()).map_err(|error| {
Http3FramePayloadBuildError::PayloadVarInt {
field: Http3FramePayloadField::PushId,
error,
}
})?;
let plan = envelope(
Http3FrameType::MAX_PUSH_ID,
push_id.byte_len(),
self.destination,
)?;
let header_length = plan.header_length();
let required = plan.required();
let bytes = &mut self.destination[..required];
plan.write_header(bytes);
bytes[header_length..].copy_from_slice(push_id.bytes());
let frame = plan.finish(bytes);
Ok(Http3MaxPushId::from_validated(
frame,
self.push_id,
push_id.len,
))
}
}