// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{frame::Tag, inet::ExplicitCongestionNotification, number::CheckedSub, varint::VarInt};
use core::{
    convert::TryInto,
    ops::{RangeInclusive, SubAssign},
};
use s2n_codec::{
    decoder_parameterized_value, decoder_value, DecoderBuffer, DecoderError, Encoder, EncoderValue,
};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3
//# Receivers send ACK frames (types 0x02 and 0x03) to inform senders of
//# packets they have received and processed.  The ACK frame contains one
//# or more ACK Ranges.  ACK Ranges identify acknowledged packets.  If
//# the frame type is 0x03, ACK frames also contain the cumulative count
//# of QUIC packets with associated ECN marks received on the connection
//# up until this point.

macro_rules! ack_tag {
    () => {
        0x02u8..=0x03u8
    };
}
const ACK_TAG: u8 = 0x02;
const ACK_W_ECN_TAG: u8 = 0x03;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3
//# ACK Frame {
//#   Type (i) = 0x02..0x03,
//#   Largest Acknowledged (i),
//#   ACK Delay (i),
//#   ACK Range Count (i),
//#   First ACK Range (i),
//#   ACK Range (..) ...,
//#   [ECN Counts (..)],
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3
//# ACK frames contain the following fields:
//#
//# Largest Acknowledged:  A variable-length integer representing the
//# largest packet number the peer is acknowledging; this is usually
//# the largest packet number that the peer has received prior to
//# generating the ACK frame.  Unlike the packet number in the QUIC
//# long or short header, the value in an ACK frame is not truncated.
//#
//# ACK Delay:  A variable-length integer encoding the acknowledgment
//# delay in microseconds; see Section 13.2.5.  It is decoded by
//# multiplying the value in the field by 2 to the power of the
//# ack_delay_exponent transport parameter sent by the sender of the
//# ACK frame; see Section 18.2.  Compared to simply expressing the
//# delay as an integer, this encoding allows for a larger range of
//# values within the same number of bytes, at the cost of lower
//# resolution.
//#
//# ACK Range Count:  A variable-length integer specifying the number of
//# ACK Range fields in the frame.
//#
//# First ACK Range:  A variable-length integer indicating the number of
//# contiguous packets preceding the Largest Acknowledged that are
//# being acknowledged.  That is, the smallest packet acknowledged in
//# the range is determined by subtracting the First ACK Range value
//# from the Largest Acknowledged field.
//#
//# ACK Ranges:  Contains additional ranges of packets that are
//# alternately not acknowledged (Gap) and acknowledged (ACK Range);
//# see Section 19.3.1.
//#
//# ECN Counts:  The three ECN counts; see Section 19.3.2.

#[derive(Clone, PartialEq, Eq)]
pub struct Ack<AckRanges> {
    /// A variable-length integer representing the time delta in microseconds
    /// between when this ACK was sent and when the largest acknowledged
    /// packet, as indicated in the Largest Acknowledged field, was
    /// received by this peer
    pub ack_delay: VarInt,

    /// Contains additional ranges of packets which are alternately not
    /// acknowledged (Gap) and acknowledged (ACK Range)
    pub ack_ranges: AckRanges,

    /// ECN Counts
    pub ecn_counts: Option<EcnCounts>,
}

impl<AckRanges> Ack<AckRanges> {
    pub fn tag(&self) -> u8 {
        if self.ecn_counts.is_some() {
            ACK_W_ECN_TAG
        } else {
            ACK_TAG
        }
    }
}

impl<A: AckRanges> Ack<A> {
    pub fn ack_delay(&self) -> core::time::Duration {
        core::time::Duration::from_micros(self.ack_delay.as_u64())
    }

    pub fn ack_ranges(&self) -> A::Iter {
        self.ack_ranges.ack_ranges()
    }

    pub fn largest_acknowledged(&self) -> VarInt {
        self.ack_ranges.largest_acknowledged()
    }
}

impl<A: core::fmt::Debug> core::fmt::Debug for Ack<A> {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        f.debug_struct("Ack")
            .field("ack_delay", &self.ack_delay)
            .field("ack_ranges", &self.ack_ranges)
            .field("ecn_counts", &self.ecn_counts)
            .finish()
    }
}

decoder_parameterized_value!(
    impl<'a> Ack<AckRangesDecoder<'a>> {
        fn decode(tag: Tag, buffer: Buffer) -> Result<Self> {
            let (largest_acknowledged, buffer) = buffer.decode()?;
            let (ack_delay, buffer) = buffer.decode()?;
            let (ack_ranges, buffer) = buffer.decode_parameterized(largest_acknowledged)?;

            let (ecn_counts, buffer) = if tag == ACK_W_ECN_TAG {
                let (ecn_counts, buffer) = buffer.decode()?;
                (Some(ecn_counts), buffer)
            } else {
                (None, buffer)
            };

            let frame = Ack {
                ack_delay,
                ack_ranges,
                ecn_counts,
            };

            Ok((frame, buffer))
        }
    }
);

impl<A: AckRanges> EncoderValue for Ack<A> {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());

        let mut iter = self.ack_ranges.ack_ranges();

        let first_ack_range = iter.next().expect("at least one ack range is required");
        let (mut smallest, largest_acknowledged) = first_ack_range.into_inner();
        let first_ack_range = largest_acknowledged - smallest;

        let ack_range_count: VarInt = iter
            .len()
            .try_into()
            .expect("ack range count cannot exceed VarInt::MAX");

        buffer.encode(&largest_acknowledged);
        buffer.encode(&self.ack_delay);
        buffer.encode(&ack_range_count);
        buffer.encode(&first_ack_range);

        for range in iter {
            smallest = encode_ack_range(range, smallest, buffer);
        }

        if let Some(ecn_counts) = self.ecn_counts.as_ref() {
            buffer.encode(ecn_counts);
        }
    }
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3.1
//# Each ACK Range consists of alternating Gap and ACK Range Length
//# values in descending packet number order.  ACK Ranges can be
//# repeated.  The number of Gap and ACK Range Length values is
//# determined by the ACK Range Count field; one of each value is present
//# for each value in the ACK Range Count field.

pub trait AckRanges {
    type Iter: Iterator<Item = RangeInclusive<VarInt>> + ExactSizeIterator;

    fn ack_ranges(&self) -> Self::Iter;

    fn largest_acknowledged(&self) -> VarInt {
        *self
            .ack_ranges()
            .next()
            .expect("at least one ack range is required")
            .end()
    }
}

#[derive(Clone, Copy)]
pub struct AckRangesDecoder<'a> {
    largest_acknowledged: VarInt,
    ack_range_count: VarInt,
    range_buffer: DecoderBuffer<'a>,
}

impl<'a> AckRanges for AckRangesDecoder<'a> {
    type Iter = AckRangesIter<'a>;

    fn ack_ranges(&self) -> Self::Iter {
        AckRangesIter {
            largest_acknowledged: self.largest_acknowledged,
            ack_range_count: self.ack_range_count,
            range_buffer: self.range_buffer,
        }
    }

    fn largest_acknowledged(&self) -> VarInt {
        self.largest_acknowledged
    }
}

impl<'a> PartialEq for AckRangesDecoder<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.ack_ranges().eq(other.ack_ranges())
    }
}

impl<'a> core::fmt::Debug for AckRangesDecoder<'a> {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        core::fmt::Debug::fmt(&self.ack_ranges(), f)
    }
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3.1
//# Each ACK Range consists of alternating Gap and ACK Range Length
//# values in descending packet number order.  ACK Ranges can be
//# repeated.  The number of Gap and ACK Range Length values is
//# determined by the ACK Range Count field; one of each value is present
//# for each value in the ACK Range Count field.

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3.1
//# ACK Range {
//#   Gap (i),
//#   ACK Range Length (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3.1
//# The fields that form each ACK Range are:
//#
//# Gap:  A variable-length integer indicating the number of contiguous
//# unacknowledged packets preceding the packet number one lower than
//# the smallest in the preceding ACK Range.
//#
//# ACK Range Length:  A variable-length integer indicating the number of
//# contiguous acknowledged packets preceding the largest packet
//# number, as determined by the preceding Gap.
//#
//# Gap and ACK Range Length values use a relative integer encoding for
//# efficiency.  Though each encoded value is positive, the values are
//# subtracted, so that each ACK Range describes progressively lower-
//# numbered packets.
//#
//# Each ACK Range acknowledges a contiguous range of packets by
//# indicating the number of acknowledged packets that precede the
//# largest packet number in that range.  A value of 0 indicates that
//# only the largest packet number is acknowledged.  Larger ACK Range
//# values indicate a larger range, with corresponding lower values for
//# the smallest packet number in the range.  Thus, given a largest
//# packet number for the range, the smallest value is determined by the
//# following formula:
//
// smallest = largest - ack_range

decoder_parameterized_value!(
    impl<'a> AckRangesDecoder<'a> {
        fn decode(largest_acknowledged: VarInt, buffer: Buffer) -> Result<AckRangesDecoder> {
            let (mut ack_range_count, buffer) = buffer.decode::<VarInt>()?;

            // add one to the total, which includes the first ack range
            ack_range_count = ack_range_count
                .checked_add(VarInt::from_u8(1))
                .ok_or(ACK_RANGE_DECODING_ERROR)?;

            let mut iter = AckRangesIter {
                ack_range_count,
                range_buffer: buffer.peek(),
                largest_acknowledged,
            };

            // make sure we can decode all of the range/gap pairs
            for _ in 0..*ack_range_count {
                iter.next().ok_or(ACK_RANGE_DECODING_ERROR)?;
            }

            let peek_len = iter.range_buffer.len();
            let buffer_len = buffer.len();
            debug_assert!(
                buffer_len >= peek_len,
                "peeked buffer should never consume more than actual buffer"
            );
            let (range_buffer, remaining) = buffer.decode_slice(buffer_len - peek_len)?;

            #[allow(clippy::useless_conversion)]
            let range_buffer = range_buffer.into();

            let ack_ranges = AckRangesDecoder {
                largest_acknowledged,
                ack_range_count,
                range_buffer,
            };

            Ok((ack_ranges, remaining))
        }
    }
);

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3.1
//# An ACK Range acknowledges all packets between the smallest packet
//# number and the largest, inclusive.
//#
//# The largest value for an ACK Range is determined by cumulatively
//# subtracting the size of all preceding ACK Range Lengths and Gaps.
//#
//# Each Gap indicates a range of packets that are not being
//# acknowledged.  The number of packets in the gap is one higher than
//# the encoded value of the Gap field.
//#
//# The value of the Gap field establishes the largest packet number
//# value for the subsequent ACK Range using the following formula:
//#
//# largest = previous_smallest - gap - 2

fn encode_ack_range<E: Encoder>(
    range: RangeInclusive<VarInt>,
    smallest: VarInt,
    buffer: &mut E,
) -> VarInt {
    let (start, end) = range.into_inner();
    let gap = smallest - end - 2;
    let ack_range = end - start;

    buffer.encode(&gap);
    buffer.encode(&ack_range);

    start
}

#[derive(Clone, Copy)]
pub struct AckRangesIter<'a> {
    largest_acknowledged: VarInt,
    ack_range_count: VarInt,
    range_buffer: DecoderBuffer<'a>,
}

impl<'a> Iterator for AckRangesIter<'a> {
    type Item = RangeInclusive<VarInt>;

    fn next(&mut self) -> Option<Self::Item> {
        self.ack_range_count = self.ack_range_count.checked_sub(VarInt::from_u8(1))?;

        let largest_acknowledged = self.largest_acknowledged;
        let (ack_range, buffer) = self.range_buffer.decode::<VarInt>().ok()?;

        let start = largest_acknowledged.checked_sub(ack_range)?;
        let end = largest_acknowledged;

        // If we're not on the last range, try to decode the next gap
        self.range_buffer = if self.ack_range_count != VarInt::from_u8(0) {
            let (gap, buffer) = buffer.decode::<VarInt>().ok()?;
            self.largest_acknowledged = largest_acknowledged
                .checked_sub(ack_range)?
                .checked_sub(gap)?
                .checked_sub(VarInt::from_u8(2))?;
            buffer
        } else {
            buffer
        };

        Some(start..=end)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let ack_range_count = *self.ack_range_count as usize;
        (ack_range_count, Some(ack_range_count))
    }
}

impl<'a> ExactSizeIterator for AckRangesIter<'a> {}

impl<'a> core::fmt::Debug for AckRangesIter<'a> {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        f.debug_list().entries(*self).finish()
    }
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3.1
//# If any computed packet number is negative, an endpoint MUST generate
//# a connection error of type FRAME_ENCODING_ERROR.

const ACK_RANGE_DECODING_ERROR: DecoderError =
    DecoderError::InvariantViolation("invalid ACK ranges");

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3.2
//# The ACK frame uses the least significant bit of the type value (that
//# is, type 0x03) to indicate ECN feedback and report receipt of QUIC
//# packets with associated ECN codepoints of ECT(0), ECT(1), or ECN-CE
//# in the packet's IP header.  ECN counts are only present when the ACK
//# frame type is 0x03.

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3.2
//# ECN Counts {
//#   ECT0 Count (i),
//#   ECT1 Count (i),
//#   ECN-CE Count (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.3.2
//# The ECN count fields are:
//#
//# ECT0 Count:  A variable-length integer representing the total number
//# of packets received with the ECT(0) codepoint in the packet number
//# space of the ACK frame.
//#
//# ECT1 Count:  A variable-length integer representing the total number
//# of packets received with the ECT(1) codepoint in the packet number
//# space of the ACK frame.
//#
//# ECN-CE Count:  A variable-length integer representing the total
//# number of packets received with the ECN-CE codepoint in the packet
//# number space of the ACK frame.
//#
//# ECN counts are maintained separately for each packet number space.
#[cfg(feature = "generator")]
use bolero_generator::*;

#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "generator", derive(TypeGenerator))]
pub struct EcnCounts {
    /// A variable-length integer representing the total number of packets
    /// received with the ECT(0) codepoint.
    pub ect_0_count: VarInt,

    /// A variable-length integer representing the total number of packets
    /// received with the ECT(1) codepoint.
    pub ect_1_count: VarInt,

    /// A variable-length integer representing the total number of packets
    /// received with the CE codepoint.
    pub ce_count: VarInt,
}

impl EcnCounts {
    /// Increment the count for the given `ExplicitCongestionNotification`
    pub fn increment(&mut self, ecn: ExplicitCongestionNotification) {
        match ecn {
            ExplicitCongestionNotification::Ect0 => {
                self.ect_0_count = self.ect_0_count.saturating_add(VarInt::from_u8(1))
            }
            ExplicitCongestionNotification::Ect1 => {
                self.ect_1_count = self.ect_1_count.saturating_add(VarInt::from_u8(1))
            }
            ExplicitCongestionNotification::Ce => {
                self.ce_count = self.ce_count.saturating_add(VarInt::from_u8(1))
            }
            ExplicitCongestionNotification::NotEct => {}
        }
    }

    /// Gets the `EcnCounts` as an Option that will be `None` if none of the `EcnCounts` have
    /// been incremented.
    pub fn as_option(&self) -> Option<EcnCounts> {
        if *self == Default::default() {
            return None;
        }

        Some(*self)
    }

    /// Return `EcnCounts` containing the maximum of each individual ECN count
    #[must_use]
    pub fn max(self, other: Self) -> Self {
        EcnCounts {
            ect_0_count: self.ect_0_count.max(other.ect_0_count),
            ect_1_count: self.ect_1_count.max(other.ect_1_count),
            ce_count: self.ce_count.max(other.ce_count),
        }
    }
}

impl SubAssign for EcnCounts {
    fn sub_assign(&mut self, rhs: Self) {
        self.ect_0_count = self.ect_0_count.saturating_sub(rhs.ect_0_count);
        self.ect_1_count = self.ect_1_count.saturating_sub(rhs.ect_1_count);
        self.ce_count = self.ce_count.saturating_sub(rhs.ce_count);
    }
}

impl CheckedSub for EcnCounts {
    type Output = EcnCounts;

    fn checked_sub(self, rhs: Self) -> Option<Self::Output> {
        let ect_0_count = self.ect_0_count.checked_sub(rhs.ect_0_count)?;
        let ect_1_count = self.ect_1_count.checked_sub(rhs.ect_1_count)?;
        let ce_count = self.ce_count.checked_sub(rhs.ce_count)?;

        Some(EcnCounts {
            ect_0_count,
            ect_1_count,
            ce_count,
        })
    }
}

decoder_value!(
    impl<'a> EcnCounts {
        fn decode(buffer: Buffer) -> Result<Self> {
            let (ect_0_count, buffer) = buffer.decode()?;
            let (ect_1_count, buffer) = buffer.decode()?;
            let (ce_count, buffer) = buffer.decode()?;

            let ecn_counts = Self {
                ect_0_count,
                ect_1_count,
                ce_count,
            };

            Ok((ecn_counts, buffer))
        }
    }
);

impl EncoderValue for EcnCounts {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.ect_0_count);
        buffer.encode(&self.ect_1_count);
        buffer.encode(&self.ce_count);
    }
}

#[cfg(test)]
mod tests {
    use crate::{frame::ack::EcnCounts, inet::ExplicitCongestionNotification};

    #[test]
    fn as_option() {
        let mut ecn_counts = EcnCounts::default();

        assert_eq!(None, ecn_counts.as_option());

        ecn_counts.increment(ExplicitCongestionNotification::Ect0);
        assert!(ecn_counts.as_option().is_some());

        let mut ecn_counts = EcnCounts::default();
        ecn_counts.increment(ExplicitCongestionNotification::Ect1);
        assert!(ecn_counts.as_option().is_some());

        let mut ecn_counts = EcnCounts::default();
        ecn_counts.increment(ExplicitCongestionNotification::Ce);
        assert!(ecn_counts.as_option().is_some());
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use core::ops::{BitOr, BitOrAssign};

//= https://www.rfc-editor.org/rfc/rfc9002#section-2
//# Ack-eliciting packets:  Packets that contain ack-eliciting frames
//#    elicit an ACK from the receiver within the maximum acknowledgement
//#    delay and are called ack-eliciting packets.

/// Describes if a frame or packet requires an ACK from the peer
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AckElicitation {
    NonEliciting,
    Eliciting,
}

impl Default for AckElicitation {
    fn default() -> Self {
        Self::NonEliciting
    }
}

impl AckElicitation {
    /// Returns true if the `AckElicitation` is set to `Eliciting`
    pub fn is_ack_eliciting(self) -> bool {
        matches!(self, Self::Eliciting)
    }
}

impl BitOr<AckElicitation> for AckElicitation {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self {
        match (self, rhs) {
            (Self::Eliciting, _) => Self::Eliciting,
            (_, Self::Eliciting) => Self::Eliciting,
            (_, _) => Self::NonEliciting,
        }
    }
}

impl BitOrAssign<AckElicitation> for AckElicitation {
    fn bitor_assign(&mut self, rhs: Self) {
        *self = *self | rhs;
    }
}

/// Trait to retrieve the AckElicitation for a given value
pub trait AckElicitable {
    #[inline]
    fn ack_elicitation(&self) -> AckElicitation {
        AckElicitation::Eliciting
    }
}

//= https://www.rfc-editor.org/rfc/rfc9002#section-2
//# Ack-eliciting Frames:  All frames other than ACK, PADDING, and
//#    CONNECTION_CLOSE are considered ack-eliciting.

impl<AckRanges> AckElicitable for crate::frame::Ack<AckRanges> {
    #[inline]
    fn ack_elicitation(&self) -> AckElicitation {
        AckElicitation::NonEliciting
    }
}
impl AckElicitable for crate::frame::ConnectionClose<'_> {
    #[inline]
    fn ack_elicitation(&self) -> AckElicitation {
        AckElicitation::NonEliciting
    }
}
impl<Data> AckElicitable for crate::frame::Crypto<Data> {}
//= https://www.rfc-editor.org/rfc/rfc9221#section-5.2
//# Although DATAGRAM frames are not retransmitted upon loss detection,
//# they are ack-eliciting ([RFC9002]).
impl<Data> AckElicitable for crate::frame::Datagram<Data> {}
impl AckElicitable for crate::frame::DataBlocked {}
impl AckElicitable for crate::frame::HandshakeDone {}
impl AckElicitable for crate::frame::MaxData {}
impl AckElicitable for crate::frame::MaxStreamData {}
impl AckElicitable for crate::frame::MaxStreams {}
impl AckElicitable for crate::frame::NewConnectionId<'_> {}
impl AckElicitable for crate::frame::NewToken<'_> {}
impl AckElicitable for crate::frame::Padding {
    #[inline]
    fn ack_elicitation(&self) -> AckElicitation {
        AckElicitation::NonEliciting
    }
}
impl AckElicitable for crate::frame::PathChallenge<'_> {}
impl AckElicitable for crate::frame::PathResponse<'_> {}
impl AckElicitable for crate::frame::Ping {}
impl AckElicitable for crate::frame::ResetStream {}
impl AckElicitable for crate::frame::RetireConnectionId {}
impl AckElicitable for crate::frame::StopSending {}
impl<Data> AckElicitable for crate::frame::Stream<Data> {}
impl AckElicitable for crate::frame::StreamDataBlocked {}
impl AckElicitable for crate::frame::StreamsBlocked {}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//= https://www.rfc-editor.org/rfc/rfc9002#section-7
//# Similar to TCP, packets containing only ACK frames do not count
//# towards bytes in flight and are not congestion controlled.

/// Trait to retrieve CongestionControlled for a given value
pub trait CongestionControlled {
    #[inline]
    fn is_congestion_controlled(&self) -> bool {
        true
    }
}

impl<AckRanges> CongestionControlled for crate::frame::Ack<AckRanges> {
    #[inline]
    fn is_congestion_controlled(&self) -> bool {
        false
    }
}
impl CongestionControlled for crate::frame::ConnectionClose<'_> {}
impl<Data> CongestionControlled for crate::frame::Crypto<Data> {}
//= https://www.rfc-editor.org/rfc/rfc9221#section-5.4
//# DATAGRAM frames employ the QUIC connection's congestion controller.
impl<Data> CongestionControlled for crate::frame::Datagram<Data> {}
impl CongestionControlled for crate::frame::DataBlocked {}
impl CongestionControlled for crate::frame::HandshakeDone {}
impl CongestionControlled for crate::frame::MaxData {}
impl CongestionControlled for crate::frame::MaxStreamData {}
impl CongestionControlled for crate::frame::MaxStreams {}
impl CongestionControlled for crate::frame::NewConnectionId<'_> {}
impl CongestionControlled for crate::frame::NewToken<'_> {}
impl CongestionControlled for crate::frame::Padding {
    //= https://www.rfc-editor.org/rfc/rfc9002#section-2
    //= type=exception
    //= reason=https://github.com/aws/s2n-quic/pull/1514
    //# Packets are considered in flight when they are ack-eliciting or contain a PADDING frame

    //= https://www.rfc-editor.org/rfc/rfc9002#section-3
    //= type=exception
    //= reason=https://github.com/aws/s2n-quic/pull/1514
    //# PADDING frames cause packets to contribute toward bytes in
    //# flight without directly causing an acknowledgment to be sent.

    #[inline]
    fn is_congestion_controlled(&self) -> bool {
        false
    }
}
impl CongestionControlled for crate::frame::PathChallenge<'_> {}
impl CongestionControlled for crate::frame::PathResponse<'_> {}
impl CongestionControlled for crate::frame::Ping {}
impl CongestionControlled for crate::frame::ResetStream {}
impl CongestionControlled for crate::frame::RetireConnectionId {}
impl CongestionControlled for crate::frame::StopSending {}
impl CongestionControlled for crate::frame::StreamsBlocked {}
impl CongestionControlled for crate::frame::StreamDataBlocked {}
impl<Data> CongestionControlled for crate::frame::Stream<Data> {}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{application, frame::Tag, varint::VarInt};
use s2n_codec::{decoder_parameterized_value, Encoder, EncoderValue};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.19
//# An endpoint sends a CONNECTION_CLOSE frame (type=0x1c or 0x1d) to
//# notify its peer that the connection is being closed.  The
//# CONNECTION_CLOSE frame with a type of 0x1c is used to signal errors
//# at only the QUIC layer, or the absence of errors (with the NO_ERROR
//# code).  The CONNECTION_CLOSE frame with a type of 0x1d is used to
//# signal an error with the application that uses QUIC.

macro_rules! connection_close_tag {
    () => {
        0x1cu8..=0x1du8
    };
}
const QUIC_ERROR_TAG: u8 = 0x1c;
const APPLICATION_ERROR_TAG: u8 = 0x1d;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.19
//# CONNECTION_CLOSE Frame {
//#   Type (i) = 0x1c..0x1d,
//#   Error Code (i),
//#   [Frame Type (i)],
//#   Reason Phrase Length (i),
//#   Reason Phrase (..),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.19
//# CONNECTION_CLOSE frames contain the following fields:
//#
//# Error Code:  A variable-length integer that indicates the reason for
//# closing this connection.  A CONNECTION_CLOSE frame of type 0x1c
//# uses codes from the space defined in Section 20.1.  A
//# CONNECTION_CLOSE frame of type 0x1d uses codes defined by the
//# application protocol; see Section 20.2.
//#
//# Frame Type:  A variable-length integer encoding the type of frame
//# that triggered the error.  A value of 0 (equivalent to the mention
//# of the PADDING frame) is used when the frame type is unknown.  The
//# application-specific variant of CONNECTION_CLOSE (type 0x1d) does
//# not include this field.
//#
//# Reason Phrase Length:  A variable-length integer specifying the
//# length of the reason phrase in bytes.  Because a CONNECTION_CLOSE
//# frame cannot be split between packets, any limits on packet size
//# will also limit the space available for a reason phrase.
//#
//# Reason Phrase:  Additional diagnostic information for the closure.
//# This can be zero length if the sender chooses not to give details
//# beyond the Error Code value.  This SHOULD be a UTF-8 encoded
//# string [RFC3629], though the frame does not carry information,
//# such as language tags, that would aid comprehension by any entity
//# other than the one that created the text.

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ConnectionClose<'a> {
    /// A variable length integer error code which indicates the reason
    /// for closing this connection.
    pub error_code: VarInt,

    /// A variable-length integer encoding the type of frame that
    /// triggered the error.
    pub frame_type: Option<VarInt>,

    /// A human-readable explanation for why the connection was closed.
    /// This SHOULD be a UTF-8 encoded string.
    pub reason: Option<&'a [u8]>,
}

impl<'a> ConnectionClose<'a> {
    pub fn tag(&self) -> u8 {
        if self.frame_type.is_some() {
            QUIC_ERROR_TAG
        } else {
            APPLICATION_ERROR_TAG
        }
    }
}

// If a `ConnectionClose` contains no frame type it was sent by an application and contains
// an `ApplicationErrorCode`. Otherwise it is an error on the QUIC layer.
impl<'a> application::error::TryInto for ConnectionClose<'a> {
    fn application_error(&self) -> Option<application::Error> {
        if self.frame_type.is_none() {
            Some(self.error_code.into())
        } else {
            None
        }
    }
}

decoder_parameterized_value!(
    impl<'a> ConnectionClose<'a> {
        fn decode(tag: Tag, buffer: Buffer) -> Result<Self> {
            let (error_code, buffer) = buffer.decode()?;

            let (frame_type, buffer) = if tag == QUIC_ERROR_TAG {
                let (frame_type, buffer) = buffer.decode()?;
                (Some(frame_type), buffer)
            } else {
                (None, buffer)
            };

            let (reason, buffer) = buffer.decode_slice_with_len_prefix::<VarInt>()?;

            let reason = if reason.is_empty() {
                None
            } else {
                // newer versions of clippy complain about redundant slicing
                // but we don't know if this is a `&slice` or `&mut slice`
                #[allow(clippy::all)]
                Some(&reason.into_less_safe_slice()[..])
            };

            let frame = ConnectionClose {
                error_code,
                frame_type,
                reason,
            };

            Ok((frame, buffer))
        }
    }
);

impl<'a> EncoderValue for ConnectionClose<'a> {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());

        buffer.encode(&self.error_code);
        if let Some(frame_type) = &self.frame_type {
            buffer.encode(frame_type);
        }

        if let Some(reason) = &self.reason {
            buffer.encode_with_len_prefix::<VarInt, _>(reason);
        } else {
            buffer.encode(&0u8);
        }
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{
    frame::{FitError, Tag},
    varint::VarInt,
};
use core::{convert::TryFrom, mem::size_of};
use s2n_codec::{
    decoder_parameterized_value, DecoderBuffer, DecoderBufferMut, Encoder, EncoderValue,
};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.6
//# A CRYPTO frame (type=0x06) is used to transmit cryptographic
//# handshake messages.

macro_rules! crypto_tag {
    () => {
        0x06u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.6
//# CRYPTO Frame {
//#   Type (i) = 0x06,
//#   Offset (i),
//#   Length (i),
//#   Crypto Data (..),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.6
//# CRYPTO frames contain the following fields:
//#
//# Offset:  A variable-length integer specifying the byte offset in the
//#    stream for the data in this CRYPTO frame.
//#
//# Length:  A variable-length integer specifying the length of the
//#    Crypto Data field in this CRYPTO frame.
//#
//# Crypto Data:  The cryptographic message data.

#[derive(Debug, PartialEq, Eq)]
pub struct Crypto<Data> {
    /// A variable-length integer specifying the byte offset in the stream
    /// for the data in this CRYPTO frame.
    pub offset: VarInt,

    /// The cryptographic message data.
    pub data: Data,
}

impl<Data> Crypto<Data> {
    pub const fn tag(&self) -> u8 {
        crypto_tag!()
    }

    /// Converts the crypto data from one type to another
    pub fn map_data<F: FnOnce(Data) -> Out, Out>(self, map: F) -> Crypto<Out> {
        Crypto {
            offset: self.offset,
            data: map(self.data),
        }
    }
}

impl<Data: EncoderValue> Crypto<Data> {
    /// Tries to fit the frame into the provided capacity
    ///
    /// If ok, the new payload length is returned, otherwise the frame cannot
    /// fit.
    pub fn try_fit(&self, capacity: usize) -> Result<usize, FitError> {
        let mut fixed_len = 0;
        fixed_len += size_of::<Tag>();
        fixed_len += self.offset.encoding_size();

        let remaining_capacity = capacity.checked_sub(fixed_len).ok_or(FitError)?;

        let data_len = self.data.encoding_size();
        let max_data_len = remaining_capacity.min(data_len);

        let len_prefix_size = VarInt::try_from(max_data_len)
            .map_err(|_| FitError)?
            .encoding_size();

        let prefixed_data_len = remaining_capacity
            .checked_sub(len_prefix_size)
            .ok_or(FitError)?;
        let data_len = prefixed_data_len.min(data_len);

        Ok(data_len)
    }
}

pub type CryptoRef<'a> = Crypto<&'a [u8]>;
pub type CryptoMut<'a> = Crypto<&'a mut [u8]>;

decoder_parameterized_value!(
    impl<'a, Data> Crypto<Data> {
        fn decode(_tag: Tag, buffer: Buffer) -> Result<Self> {
            let (offset, buffer) = buffer.decode()?;
            let (data, buffer) = buffer.decode_with_len_prefix::<VarInt, Data>()?;

            let frame = Crypto { offset, data };

            Ok((frame, buffer))
        }
    }
);

impl<Data: EncoderValue> EncoderValue for Crypto<Data> {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());
        buffer.encode(&self.offset);
        buffer.encode_with_len_prefix::<VarInt, _>(&self.data);
    }
}

impl<'a> From<Crypto<DecoderBuffer<'a>>> for CryptoRef<'a> {
    fn from(s: Crypto<DecoderBuffer<'a>>) -> Self {
        s.map_data(|data| data.into_less_safe_slice())
    }
}

impl<'a> From<Crypto<DecoderBufferMut<'a>>> for CryptoRef<'a> {
    fn from(s: Crypto<DecoderBufferMut<'a>>) -> Self {
        s.map_data(|data| &*data.into_less_safe_slice())
    }
}

impl<'a> From<Crypto<DecoderBufferMut<'a>>> for CryptoMut<'a> {
    fn from(s: Crypto<DecoderBufferMut<'a>>) -> Self {
        s.map_data(|data| data.into_less_safe_slice())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::frame::Padding;
    use bolero::check;
    use core::convert::TryInto;

    fn model(offset: VarInt, length: VarInt, capacity: usize) {
        let length = if let Ok(length) = VarInt::try_into(length) {
            length
        } else {
            // if the length cannot be represented by `usize` then bail
            return;
        };

        let mut frame = Crypto {
            offset,
            data: Padding { length },
        };

        if let Ok(new_length) = frame.try_fit(capacity) {
            frame.data = Padding { length: new_length };

            assert!(
                frame.encoding_size() <= capacity,
                "the encoding_size should not exceed capacity {:#?}",
                frame
            );

            if new_length < length {
                // Ideally `frame.encoding_size() == capacity` but in some cases, the payload
                // needs to be decreased to fit `capacity` and by decreasing the payload size,
                // the length prefix is also decreased.
                //
                // The tolerance is based on the length prefix encoding size.
                // For example, if the length prefix requires 2 bytes to encode the length,
                // the overall `frame.encoding_size()` can be within 2 bytes of `capacity`.
                let tolerance = VarInt::try_from(new_length).unwrap().encoding_size();

                assert!(
                    capacity - frame.encoding_size() <= tolerance,
                    "should fit capacity tolerance: expected {}, got {}; {:#?}",
                    tolerance,
                    capacity - frame.encoding_size(),
                    frame,
                );
            }
        } else {
            assert!(
                frame.encoding_size() > capacity,
                "rejection should only occur when encoding size > capacity {:#?}",
                frame
            );
        }
    }

    #[test]
    #[cfg_attr(kani, kani::proof, kani::unwind(1), kani::solver(kissat))]
    fn try_fit_test() {
        check!()
            .with_type()
            .cloned()
            .for_each(|(offset, length, capacity)| {
                model(offset, length, capacity);
            });
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{frame::Tag, varint::VarInt};

use s2n_codec::{
    decoder_parameterized_value, DecoderBuffer, DecoderBufferMut, Encoder, EncoderValue,
};

//= https://www.rfc-editor.org/rfc/rfc9221#section-4
//# DATAGRAM frames are used to transmit application data in an
//# unreliable manner.  The Type field in the DATAGRAM frame takes the
//# form 0b0011000X (or the values 0x30 and 0x31).

macro_rules! datagram_tag {
    () => {
        0x30u8..=0x31u8
    };
}

pub const DATAGRAM_TAG: u8 = 0x30;
//= https://www.rfc-editor.org/rfc/rfc9221#section-4
//# The least significant bit of the Type field in the DATAGRAM frame is
//# the LEN bit (0x01), which indicates whether there is a Length field
//# present: if this bit is set to 0, the Length field is absent and the
//# Datagram Data field extends to the end of the packet; if this bit is
//# set to 1, the Length field is present.

const LEN_BIT: u8 = 0x01;

//= https://www.rfc-editor.org/rfc/rfc9221#section-4
//# DATAGRAM Frame {
//#   Type (i) = 0x30..0x31,
//#   [Length (i)],
//#   Datagram Data (..),
//# }

//= https://www.rfc-editor.org/rfc/rfc9221#section-4
//# DATAGRAM frames contain the following fields:
//#
//# Length:  A variable-length integer specifying the length of the
//#    Datagram Data field in bytes.  This field is present only when the
//#    LEN bit is set to 1.  When the LEN bit is set to 0, the Datagram
//#    Data field extends to the end of the QUIC packet.  Note that empty
//#    (i.e., zero-length) datagrams are allowed.
//#
//# Datagram Data:  The bytes of the datagram to be delivered.

pub type DatagramRef<'a> = Datagram<&'a [u8]>;
pub type DatagramMut<'a> = Datagram<&'a mut [u8]>;

#[derive(Debug, PartialEq, Eq)]
pub struct Datagram<Data> {
    /// If true, the frame is the last frame in the payload
    pub is_last_frame: bool,

    /// The bytes to be delivered.
    pub data: Data,
}

impl<Data> Datagram<Data> {
    #[inline]
    pub fn tag(&self) -> u8 {
        let mut tag: u8 = DATAGRAM_TAG;

        if !self.is_last_frame {
            tag |= LEN_BIT;
        }

        tag
    }

    /// Converts the datagram data from one type to another
    pub fn map_data<F: FnOnce(Data) -> Out, Out>(self, map: F) -> Datagram<Out> {
        Datagram {
            is_last_frame: self.is_last_frame,
            data: map(self.data),
        }
    }
}

decoder_parameterized_value!(
    impl<'a, Data> Datagram<Data> {
        fn decode(tag: Tag, buffer: Buffer) -> Result<Self> {
            let is_last_frame = tag & LEN_BIT != LEN_BIT;

            let (data, buffer) = if !is_last_frame {
                let (data, buffer) = buffer.decode_with_len_prefix::<VarInt, Data>()?;
                (data, buffer)
            } else {
                let len = buffer.len();
                let (data, buffer) = buffer.decode_slice(len)?;
                let (data, remaining) = data.decode()?;
                remaining.ensure_empty()?;
                (data, buffer)
            };

            let frame = Datagram {
                is_last_frame,
                data,
            };

            Ok((frame, buffer))
        }
    }
);

impl<Data: EncoderValue> EncoderValue for Datagram<Data> {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());

        if self.is_last_frame {
            buffer.encode(&self.data);
        } else {
            buffer.encode_with_len_prefix::<VarInt, _>(&self.data);
        }
    }
}

impl<'a> From<Datagram<DecoderBuffer<'a>>> for DatagramRef<'a> {
    #[inline]
    fn from(d: Datagram<DecoderBuffer<'a>>) -> Self {
        d.map_data(|data| data.into_less_safe_slice())
    }
}

impl<'a> From<Datagram<DecoderBufferMut<'a>>> for DatagramRef<'a> {
    #[inline]
    fn from(d: Datagram<DecoderBufferMut<'a>>) -> Self {
        d.map_data(|data| &*data.into_less_safe_slice())
    }
}

impl<'a> From<Datagram<DecoderBufferMut<'a>>> for DatagramMut<'a> {
    #[inline]
    fn from(d: Datagram<DecoderBufferMut<'a>>) -> Self {
        d.map_data(|data| data.into_less_safe_slice())
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::varint::VarInt;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.12
//# A sender SHOULD send a DATA_BLOCKED frame (type=0x14) when it wishes
//# to send data, but is unable to do so due to connection-level flow
//# control; see Section 4.  DATA_BLOCKED frames can be used as input to
//# tuning of flow control algorithms; see Section 4.2.

macro_rules! data_blocked_tag {
    () => {
        0x14u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.12
//# DATA_BLOCKED Frame {
//#   Type (i) = 0x14,
//#   Maximum Data (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.12
//# DATA_BLOCKED frames contain the following field:
//#
//# Maximum Data:  A variable-length integer indicating the connection-
//#    level limit at which blocking occurred.

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DataBlocked {
    /// A variable-length integer indicating the connection-level limit
    /// at which blocking occurred.
    pub data_limit: VarInt,
}

impl DataBlocked {
    pub const fn tag(self) -> u8 {
        data_blocked_tag!()
    }
}

simple_frame_codec!(DataBlocked { data_limit }, data_blocked_tag!());


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.20
//# The server uses a HANDSHAKE_DONE frame (type=0x1e) to signal
//# confirmation of the handshake to the client.

macro_rules! handshake_done_tag {
    () => {
        0x1eu8
    };
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct HandshakeDone;

impl HandshakeDone {
    pub const fn tag(self) -> u8 {
        handshake_done_tag!()
    }
}

simple_frame_codec!(HandshakeDone {}, handshake_done_tag!());


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::varint::VarInt;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.9
//# A MAX_DATA frame (type=0x10) is used in flow control to inform the
//# peer of the maximum amount of data that can be sent on the connection
//# as a whole.

macro_rules! max_data_tag {
    () => {
        0x10u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.9
//# MAX_DATA Frame {
//#   Type (i) = 0x10,
//#   Maximum Data (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.9
//# MAX_DATA frames contain the following field:
//#
//# Maximum Data:  A variable-length integer indicating the maximum
//#    amount of data that can be sent on the entire connection, in units
//#    of bytes.

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MaxData {
    /// A variable-length integer indicating the maximum amount of data
    /// that can be sent on the entire connection, in units of bytes.
    pub maximum_data: VarInt,
}

impl MaxData {
    pub const fn tag(self) -> u8 {
        max_data_tag!()
    }
}

simple_frame_codec!(MaxData { maximum_data }, max_data_tag!());


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{frame::Tag, stream::StreamType, varint::VarInt};
use s2n_codec::{decoder_invariant, decoder_parameterized_value, Encoder, EncoderValue};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.11
//# A MAX_STREAMS frame (type=0x12 or 0x13) inform the peer of the
//# cumulative number of streams of a given type it is permitted to open.
//# A MAX_STREAMS frame with a type of 0x12 applies to bidirectional
//# streams, and a MAX_STREAMS frame with a type of 0x13 applies to
//# unidirectional streams.

macro_rules! max_streams_tag {
    () => {
        0x12u8..=0x13u8
    };
}
const BIDIRECTIONAL_TAG: u8 = 0x12;
const UNIDIRECTIONAL_TAG: u8 = 0x13;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.11
//# MAX_STREAMS Frame {
//#   Type (i) = 0x12..0x13,
//#   Maximum Streams (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.11
//# MAX_STREAMS frames contain the following field:
//#
//# Maximum Streams:  A count of the cumulative number of streams of the
//#    corresponding type that can be opened over the lifetime of the
//#    connection.

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MaxStreams {
    pub stream_type: StreamType,

    /// A count of the cumulative number of streams of the corresponding
    /// type that can be opened over the lifetime of the connection.
    pub maximum_streams: VarInt,
}

impl MaxStreams {
    pub fn tag(&self) -> u8 {
        match self.stream_type {
            StreamType::Bidirectional => BIDIRECTIONAL_TAG,
            StreamType::Unidirectional => UNIDIRECTIONAL_TAG,
        }
    }
}

decoder_parameterized_value!(
    impl<'a> MaxStreams {
        fn decode(tag: Tag, buffer: Buffer) -> Result<Self> {
            let stream_type = if BIDIRECTIONAL_TAG == tag {
                StreamType::Bidirectional
            } else {
                StreamType::Unidirectional
            };

            let (maximum_streams, buffer) = buffer.decode::<VarInt>()?;

            //= https://www.rfc-editor.org/rfc/rfc9000#section-4.6
            //# If a max_streams transport parameter or a MAX_STREAMS frame is
            //# received with a value greater than 2^60, this would allow a maximum
            //# stream ID that cannot be expressed as a variable-length integer; see
            //# Section 16.  If either is received, the connection MUST be closed
            //# immediately with a connection error of type TRANSPORT_PARAMETER_ERROR
            //# if the offending value was received in a transport parameter or of
            //# type FRAME_ENCODING_ERROR if it was received in a frame; see
            //# Section 10.2.

            //= https://www.rfc-editor.org/rfc/rfc9000#section-19.11
            //# This value cannot exceed 2^60, as it is not possible
            //# to encode stream IDs larger than 2^62-1.  Receipt of a frame that
            //# permits opening of a stream larger than this limit MUST be treated
            //# as a connection error of type FRAME_ENCODING_ERROR.
            decoder_invariant!(
                *maximum_streams <= 2u64.pow(60),
                "maximum streams cannot exceed 2^60"
            );

            let frame = MaxStreams {
                stream_type,
                maximum_streams,
            };

            Ok((frame, buffer))
        }
    }
);

impl EncoderValue for MaxStreams {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());
        buffer.encode(&self.maximum_streams);
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::varint::VarInt;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.10
//# A MAX_STREAM_DATA frame (type=0x11) is used in flow control to inform
//# a peer of the maximum amount of data that can be sent on a stream.

macro_rules! max_stream_data_tag {
    () => {
        0x11u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.10
//# MAX_STREAM_DATA Frame {
//#   Type (i) = 0x11,
//#   Stream ID (i),
//#   Maximum Stream Data (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.10
//# MAX_STREAM_DATA frames contain the following fields:
//#
//# Stream ID:  The stream ID of the affected stream, encoded as a
//# variable-length integer.
//#
//# Maximum Stream Data:  A variable-length integer indicating the
//# maximum amount of data that can be sent on the identified stream,
//# in units of bytes.

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MaxStreamData {
    /// The stream ID of the stream that is affected encoded as a
    /// variable-length integer.
    pub stream_id: VarInt,

    /// A variable-length integer indicating the maximum amount of data
    /// that can be sent on the identified stream, in units of bytes.
    pub maximum_stream_data: VarInt,
}

impl MaxStreamData {
    pub const fn tag(&self) -> u8 {
        max_stream_data_tag!()
    }
}

simple_frame_codec!(
    MaxStreamData {
        stream_id,
        maximum_stream_data
    },
    max_stream_data_tag!()
);


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use crate::{
    event,
    frame::{ack_elicitation::AckElicitable, congestion_controlled::CongestionControlled},
};
use core::fmt;
use s2n_codec::{
    DecoderBuffer, DecoderBufferMut, DecoderBufferMutResult, DecoderError,
    DecoderParameterizedValueMut, DecoderValueMut, Encoder, EncoderValue,
};

pub mod ack_elicitation;
pub mod congestion_controlled;
pub mod path_validation;

#[cfg(test)]
mod tests;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19
//# As described in Section 12.4, packets contain one or more frames.
//# This section describes the format and semantics of the core QUIC
//# frame types.

pub(crate) type Tag = u8;

pub type FrameRef<'a> = Frame<'a, ack::AckRangesDecoder<'a>, DecoderBuffer<'a>>;
pub type FrameMut<'a> = Frame<'a, ack::AckRangesDecoder<'a>, DecoderBufferMut<'a>>;

pub trait FrameTrait: AckElicitable + CongestionControlled + path_validation::Probing {}

/// Implement FrameTrait for all types that implement the required subtraits
impl<T: AckElicitable + CongestionControlled + path_validation::Probing> FrameTrait for T {}

macro_rules! frames {
    ($ack:ident, $data:ident | $($tag_macro:ident => $module:ident, $handler:ident, $ty:ident $([$($generics:tt)+])?;)*) => {
        $(
            #[macro_use]
            pub mod $module;
            pub use $module::$ty;
        )*

        pub type RemainingBuffer<'a> = Option<DecoderBufferMut<'a>>;

        #[derive(Debug, PartialEq, Eq)]
        pub enum Frame<'a, $ack, $data> {
            $(
                $ty($module::$ty $(<$($generics)*>)?),
            )*
        }

        impl<'a, $ack, $data> Frame<'a, $ack, $data> {
            #[inline]
            pub fn tag(&self) -> Tag {
                match self {
                    $(
                        Frame::$ty(frame) => frame.tag(),
                    )*
                }
            }
        }

        impl<'a, $ack, $data> event::IntoEvent<event::builder::Frame> for &Frame<'a, $ack, $data>
        where
            $ack: crate::frame::ack::AckRanges,
            $data: EncoderValue,
        {
            #[inline]
            fn into_event(self) -> event::builder::Frame {
                match self {
                    $(
                        Frame::$ty(inner) => inner.into_event(),
                    )*
                }
            }
        }

        impl<'a, $ack, $data> ack_elicitation::AckElicitable for Frame<'a, $ack, $data> {
            #[inline]
            fn ack_elicitation(&self) -> ack_elicitation::AckElicitation {
                match self {
                    $(
                        Frame::$ty(frame) => frame.ack_elicitation(),
                    )*
                }
            }
        }

        impl<'a, $ack, $data> path_validation::Probing for Frame<'a, $ack, $data> {
            #[inline]
            fn path_validation(&self) -> path_validation::Probe {
                match self {
                    $(
                        Frame::$ty(frame) => frame.path_validation(),
                    )*
                }
            }
        }

        $(
            impl<'a, $ack, $data> From<$module::$ty $(<$($generics)*>)?> for Frame<'a, $ack, $data> {
                #[inline]
                fn from(v: $module::$ty $(<$($generics)*>)?)  -> Frame<'a, $ack, $data> {
                    Frame::$ty(v)
                }
            }
        )*

        impl<'a, $ack, $data: DecoderValueMut<'a>> DecoderValueMut<'a> for Frame<'a, $ack, $data>
        where ack::Ack<$ack>: DecoderParameterizedValueMut<'a, Parameter = Tag> {
            #[inline]
            fn decode_mut(buffer: DecoderBufferMut<'a>) -> DecoderBufferMutResult<'a, Self> {
                BasicFrameDecoder.decode_frame(buffer)
            }
        }

        impl<'a, $ack: ack::AckRanges, $data: EncoderValue> EncoderValue for Frame<'a, $ack, $data> {
            #[inline]
            fn encode<E: Encoder>(&self, buffer: &mut E)  {
                match self {
                    $(
                        Frame::$ty(frame) => buffer.encode(frame),
                    )*
                }
            }
        }

        struct BasicFrameDecoder;

        impl<'a, $ack, $data: DecoderValueMut<'a>> FrameDecoder<'a, $ack, $data> for BasicFrameDecoder
        where ack::Ack<$ack>: DecoderParameterizedValueMut<'a, Parameter = Tag> {
            type Output = Frame<'a, $ack, $data>;

            $(
                #[inline]
                fn $handler(&mut self, frame: $module::$ty $(<$($generics)*>)?) -> Result<Self::Output, DecoderError> {
                    Ok(Frame::$ty(frame))
                }
            )*
        }

        pub trait FrameDecoder<'a, $ack, $data: DecoderValueMut<'a>>
        where ack::Ack<$ack>: DecoderParameterizedValueMut<'a, Parameter = Tag> {
            type Output;

            $(
                fn $handler(&mut self, frame: $module::$ty $(<$($generics)*>)?) -> Result<Self::Output, DecoderError>;
            )*

            fn handle_extension_frame(&mut self, buffer: DecoderBufferMut<'a>) -> DecoderBufferMutResult<'a, Self::Output> {
                let _ = buffer;

                Err(DecoderError::InvariantViolation("invalid frame"))
            }

            #[inline]
            fn decode_frame(
                &mut self,
                buffer: DecoderBufferMut<'a>,
            ) -> DecoderBufferMutResult<'a, Self::Output> {
                let tag = buffer.peek_byte(0)?;
                match tag {
                    // Make sure the single byte frame tags fit into a small variable-integer
                    // otherwise fallback to extension selection
                    0b0100_0000..=0xff => self.handle_extension_frame(buffer),
                    $(
                        $tag_macro!() => {
                            let buffer = buffer.skip(core::mem::size_of::<Tag>())?;
                            let (frame, buffer) = buffer.decode_parameterized(tag)?;
                            let output = self.$handler(frame)?;
                            Ok((output, buffer))
                        },
                    )*
                    _ => self.handle_extension_frame(buffer),
                }
            }
        }

        #[cfg(test)]
        mod snapshots {
            use super::*;
            use s2n_codec::assert_codec_round_trip_sample_file;

            $(
                #[test]
                fn $module() {
                    assert_codec_round_trip_sample_file!(FrameMut, concat!(
                        "src/frame/test_samples/",
                        stringify!($module),
                        ".bin"
                    ));
                }
            )*
        }
    };
}

// This implements a codec for a frame that contains simple
// values that don't vary based on the tag
macro_rules! simple_frame_codec {
    ($name:ident {
        $(
            $field:ident
        ),*
    }, $tag:expr) => {
        s2n_codec::decoder_parameterized_value!(
            impl<'a> $name {
                fn decode(_tag: crate::frame::Tag, buffer: Buffer) -> Result<Self> {
                    $(
                        let ($field, buffer) = buffer.decode()?;
                    )*

                    let frame = $name { $($field),* };

                    Ok((frame, buffer))
                }
            }
        );

        impl s2n_codec::EncoderValue for $name {
            #[inline]
            fn encode<E: s2n_codec::Encoder>(&self, buffer: &mut E) {
                buffer.encode(&$tag);
                $(
                    buffer.encode(&self.$field);
                )*
            }
        }
    };
}

frames! {
    AckRanges, Data |
    padding_tag => padding, handle_padding_frame, Padding;
    ping_tag => ping, handle_ping_frame, Ping;
    ack_tag => ack, handle_ack_frame, Ack[AckRanges];
    reset_stream_tag => reset_stream, handle_reset_stream_frame, ResetStream;
    stop_sending_tag => stop_sending, handle_stop_sending_frame, StopSending;
    crypto_tag => crypto, handle_crypto_frame, Crypto[Data];
    new_token_tag => new_token, handle_new_token_frame, NewToken['a];
    stream_tag => stream, handle_stream_frame, Stream[Data];
    max_data_tag => max_data, handle_max_data_frame, MaxData;
    max_stream_data_tag => max_stream_data, handle_max_stream_data_frame, MaxStreamData;
    max_streams_tag => max_streams, handle_max_streams_frame, MaxStreams;
    data_blocked_tag => data_blocked, handle_data_blocked_frame, DataBlocked;
    stream_data_blocked_tag => stream_data_blocked, handle_stream_data_blocked_frame, StreamDataBlocked;
    streams_blocked_tag => streams_blocked, handle_streams_blocked_frame, StreamsBlocked;
    new_connection_id_tag => new_connection_id, handle_new_connection_id_frame, NewConnectionId['a];
    retire_connection_id_tag => retire_connection_id, handle_retire_connection_id_frame, RetireConnectionId;
    path_challenge_tag => path_challenge, handle_path_challenge_frame, PathChallenge['a];
    path_response_tag => path_response, handle_path_response_frame, PathResponse['a];
    connection_close_tag => connection_close, handle_connection_close_frame, ConnectionClose['a];
    handshake_done_tag => handshake_done, handle_handshake_done_frame, HandshakeDone;
    datagram_tag => datagram, handle_datagram_frame, Datagram[Data];
}

#[derive(Clone, Copy, Debug, Default)]
/// Indicates the packet will not fit into the provided capacity
pub struct FitError;

impl fmt::Display for FitError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "the frame could not fit into the provided capacity")
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{frame::Tag, varint::VarInt};
use core::{convert::TryInto, mem::size_of};
use s2n_codec::{decoder_invariant, decoder_parameterized_value, Encoder, EncoderValue};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.15
//# An endpoint sends a NEW_CONNECTION_ID frame (type=0x18) to provide
//# its peer with alternative connection IDs that can be used to break
//# linkability when migrating connections; see Section 9.5.

macro_rules! new_connection_id_tag {
    () => {
        0x18u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.15
//# NEW_CONNECTION_ID Frame {
//#   Type (i) = 0x18,
//#   Sequence Number (i),
//#   Retire Prior To (i),
//#   Length (8),
//#   Connection ID (8..160),
//#   Stateless Reset Token (128),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.15
//# NEW_CONNECTION_ID frames contain the following fields:
//#
//# Sequence Number:  The sequence number assigned to the connection ID
//#    by the sender, encoded as a variable-length integer; see
//#    Section 5.1.1.
//#
//# Retire Prior To:  A variable-length integer indicating which
//#    connection IDs should be retired; see Section 5.1.2.
//#
//# Length:  An 8-bit unsigned integer containing the length of the
//#    connection ID.  Values less than 1 and greater than 20 are invalid
//#    and MUST be treated as a connection error of type
//#    FRAME_ENCODING_ERROR.
//#
//# Connection ID:  A connection ID of the specified length.
//#
//# Stateless Reset Token:  A 128-bit value that will be used for a
//#    stateless reset when the associated connection ID is used; see
//#    Section 10.3.

pub const STATELESS_RESET_TOKEN_LEN: usize = size_of::<u128>();

#[derive(Debug, PartialEq, Eq)]
pub struct NewConnectionId<'a> {
    /// The sequence number assigned to the connection ID by the sender
    pub sequence_number: VarInt,

    /// A variable-length integer indicating which connection IDs
    /// should be retired
    pub retire_prior_to: VarInt,

    /// The new connection ID
    pub connection_id: &'a [u8],

    /// A 128-bit value that will be used for a stateless reset when
    /// the associated connection ID is used
    pub stateless_reset_token: &'a [u8; STATELESS_RESET_TOKEN_LEN],
}

impl<'a> NewConnectionId<'a> {
    pub const fn tag(&self) -> u8 {
        new_connection_id_tag!()
    }
}

decoder_parameterized_value!(
    impl<'a> NewConnectionId<'a> {
        fn decode(_tag: Tag, buffer: Buffer) -> Result<Self> {
            let (sequence_number, buffer) = buffer.decode()?;
            let (retire_prior_to, buffer) = buffer.decode()?;

            //= https://www.rfc-editor.org/rfc/rfc9000#section-19.15
            //# The value in the Retire Prior To field
            //# MUST be less than or equal to the value in the Sequence Number field.

            //= https://www.rfc-editor.org/rfc/rfc9000#section-19.15
            //# Receiving a value in the Retire Prior To field that is greater than
            //# that in the Sequence Number field MUST be treated as a connection
            //# error of type FRAME_ENCODING_ERROR.
            decoder_invariant!(
                retire_prior_to <= sequence_number,
                "invalid retire prior to value"
            );

            let (connection_id_len, buffer) = buffer.decode::<u8>()?;

            //= https://www.rfc-editor.org/rfc/rfc9000#section-19.15
            //# Values less than 1 and greater than 20 are invalid
            //# and MUST be treated as a connection error of type
            //# FRAME_ENCODING_ERROR.
            decoder_invariant!(
                (1..=20).contains(&connection_id_len),
                "invalid connection id length"
            );

            let (connection_id, buffer) = buffer.decode_slice(connection_id_len.into())?;
            let connection_id = connection_id.into_less_safe_slice();

            let (stateless_reset_token, buffer) = buffer.decode_slice(STATELESS_RESET_TOKEN_LEN)?;
            let stateless_reset_token: &[u8] = stateless_reset_token.into_less_safe_slice();
            let stateless_reset_token = stateless_reset_token
                .try_into()
                .expect("Length has been already verified");

            let frame = NewConnectionId {
                sequence_number,
                retire_prior_to,
                connection_id,
                stateless_reset_token,
            };

            Ok((frame, buffer))
        }
    }
);

impl<'a> EncoderValue for NewConnectionId<'a> {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());
        buffer.encode(&self.sequence_number);
        buffer.encode(&self.retire_prior_to);
        buffer.encode_with_len_prefix::<u8, _>(&self.connection_id);
        buffer.encode(&self.stateless_reset_token.as_ref());
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{frame::Tag, varint::VarInt};
use s2n_codec::{decoder_invariant, decoder_parameterized_value, Encoder, EncoderValue};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.7
//# A server sends a NEW_TOKEN frame (type=0x07) to provide the client
//# with a token to send in the header of an Initial packet for a future
//# connection.

macro_rules! new_token_tag {
    () => {
        0x07u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.7
//# NEW_TOKEN Frame {
//#   Type (i) = 0x07,
//#   Token Length (i),
//#   Token (..),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.7
//# NEW_TOKEN frames contain the following fields:
//#
//# Token Length:  A variable-length integer specifying the length of the
//# token in bytes.
//#
//# Token:  An opaque blob that the client can use with a future Initial
//# packet.  The token MUST NOT be empty.  A client MUST treat receipt
//# of a NEW_TOKEN frame with an empty Token field as a connection
//# error of type FRAME_ENCODING_ERROR.

#[derive(Debug, PartialEq, Eq)]
pub struct NewToken<'a> {
    /// An opaque blob that the client may use with a future Initial packet.
    pub token: &'a [u8],
}

impl<'a> NewToken<'a> {
    pub const fn tag(&self) -> u8 {
        new_token_tag!()
    }
}

decoder_parameterized_value!(
    impl<'a> NewToken<'a> {
        fn decode(_tag: Tag, buffer: Buffer) -> Result<Self> {
            let (token, buffer) = buffer.decode_slice_with_len_prefix::<VarInt>()?;
            let token = token.into_less_safe_slice();

            //= https://www.rfc-editor.org/rfc/rfc9000#section-19.7
            //# A client MUST treat receipt of a NEW_TOKEN frame
            //# with an empty Token field as a connection error
            //# of type FRAME_ENCODING_ERROR.
            decoder_invariant!(!token.is_empty(), "empty Token field");

            let frame = NewToken { token };

            Ok((frame, buffer))
        }
    }
);

impl<'a> EncoderValue for NewToken<'a> {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());
        buffer.encode_with_len_prefix::<VarInt, _>(&self.token);
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::frame::Tag;
use s2n_codec::{decoder_parameterized_value, Encoder, EncoderValue};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.1
//# A PADDING frame (type=0x00) has no semantic value.  PADDING frames
//# can be used to increase the size of a packet.  Padding can be used to
//# increase an Initial packet to the minimum required size or to provide
//# protection against traffic analysis for protected packets.

macro_rules! padding_tag {
    () => {
        0x00u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.1
//# PADDING Frame {
//#   Type (i) = 0x00,
//# }

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Padding {
    pub length: usize,
}

impl Padding {
    /// The maximum padding allowed. When placed at the end of the packet
    /// all of the remaining bytes will be consumed.
    pub const MAX: Self = Self {
        length: core::usize::MAX,
    };

    pub const fn tag(self) -> u8 {
        padding_tag!()
    }
}

decoder_parameterized_value!(
    impl<'a> Padding {
        fn decode(_tag: Tag, buffer: Buffer) -> Result<Self> {
            let mut length = 0;
            while buffer
                .peek_byte(length)
                .map(|v| v == padding_tag!())
                .unwrap_or(false)
            {
                length += 1;
            }

            let buffer = buffer.skip(length).expect("padding already verified");

            // add one for tag itself - this needs to come after the skip, as the
            // tag has already been read.
            length += 1;

            let frame = Padding { length };

            Ok((frame, buffer))
        }
    }
);

impl EncoderValue for Padding {
    fn encode<E: Encoder>(&self, encoder: &mut E) {
        encoder.write_repeated(self.length, 0)
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::frame::Tag;
use core::convert::TryInto;
use s2n_codec::{decoder_parameterized_value, Encoder, EncoderValue};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.17
//# Endpoints can use PATH_CHALLENGE frames (type=0x1a) to check
//# reachability to the peer and for path validation during connection
//# migration.

macro_rules! path_challenge_tag {
    () => {
        0x1au8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.17
//# PATH_CHALLENGE Frame {
//#   Type (i) = 0x1a,
//#   Data (64),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.17
//# PATH_CHALLENGE frames contain the following fields:
//#
//# Data:  This 8-byte field contains arbitrary data.

pub const DATA_LEN: usize = 8;

#[derive(Debug, PartialEq, Eq)]
pub struct PathChallenge<'a> {
    /// This 8-byte field contains arbitrary data.
    pub data: &'a [u8; DATA_LEN],
}

impl<'a> PathChallenge<'a> {
    pub const fn tag(&self) -> u8 {
        path_challenge_tag!()
    }
}

decoder_parameterized_value!(
    impl<'a> PathChallenge<'a> {
        fn decode(_tag: Tag, buffer: Buffer) -> Result<Self> {
            let (data, buffer) = buffer.decode_slice(DATA_LEN)?;
            let data: &[u8] = data.into_less_safe_slice();

            let data = data.try_into().expect("Length has been already verified");

            let frame = PathChallenge { data };

            Ok((frame, buffer))
        }
    }
);

impl<'a> EncoderValue for PathChallenge<'a> {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());
        buffer.encode(&self.data.as_ref());
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::frame::Tag;
use s2n_codec::{decoder_parameterized_value, Encoder, EncoderValue};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.18
//# A PATH_RESPONSE frame (type=0x1b) is sent in response to a
//# PATH_CHALLENGE frame.

macro_rules! path_response_tag {
    () => {
        0x1bu8
    };
}
use crate::frame::path_challenge::{PathChallenge, DATA_LEN};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.18
//# PATH_RESPONSE Frame {
//#   Type (i) = 0x1b,
//#   Data (64),
//# }

#[derive(Debug, PartialEq, Eq)]
pub struct PathResponse<'a> {
    /// This 8-byte field contains arbitrary data.
    pub data: &'a [u8; DATA_LEN],
}

impl<'a> PathResponse<'a> {
    pub const fn tag(&self) -> u8 {
        path_response_tag!()
    }
}

impl<'a> From<PathChallenge<'a>> for PathResponse<'a> {
    fn from(path_challenge: PathChallenge<'a>) -> Self {
        Self {
            data: path_challenge.data,
        }
    }
}

decoder_parameterized_value!(
    impl<'a> PathResponse<'a> {
        fn decode(_tag: Tag, buffer: Buffer) -> Result<Self> {
            let (path_challenge, buffer) =
                buffer.decode_parameterized::<PathChallenge>(path_challenge_tag!())?;
            Ok((path_challenge.into(), buffer))
        }
    }
);

impl<'a> EncoderValue for PathResponse<'a> {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());
        buffer.encode(&self.data.as_ref());
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use core::ops::{BitOr, BitOrAssign};

#[cfg(any(test, feature = "generator"))]
use bolero_generator::*;

/// Describes if a frame is probing
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(any(feature = "generator", test), derive(TypeGenerator))]
pub enum Probe {
    NonProbing,
    Probing,
}

impl Probe {
    /// Returns true if the `Probe` is set to `Probing`
    pub fn is_probing(self) -> bool {
        matches!(self, Self::Probing)
    }
}

impl Default for Probe {
    /// A packet is Probing only if all frames within the packet are
    /// also Probing.
    ///
    /// This coupled with the Bit-Or logic makes `Probing` a good default:
    /// Probing | Probing = Probing
    /// Probing | NonProbing = NonProbing
    fn default() -> Self {
        Self::Probing
    }
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-9.1
//# A packet containing only probing frames is a "probing packet", and a
//# packet containing any other frame is a "non-probing packet".
impl BitOr<Probe> for Probe {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self {
        match (self, rhs) {
            (Self::Probing, Self::Probing) => Self::Probing,
            (_, _) => Self::NonProbing,
        }
    }
}

impl BitOrAssign<Probe> for Probe {
    fn bitor_assign(&mut self, rhs: Self) {
        *self = *self | rhs;
    }
}

/// Trait to retrieve if a frame is probing
pub trait Probing {
    #[inline]
    fn path_validation(&self) -> Probe {
        Probe::NonProbing
    }
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-9.1
//# PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID, and PADDING frames
//# are "probing frames", and all other frames are "non-probing frames".
impl<AckRanges> Probing for crate::frame::Ack<AckRanges> {}
impl Probing for crate::frame::ConnectionClose<'_> {}
impl<Data> Probing for crate::frame::Crypto<Data> {}
impl<Data> Probing for crate::frame::Datagram<Data> {}
impl Probing for crate::frame::DataBlocked {}
impl Probing for crate::frame::HandshakeDone {}
impl Probing for crate::frame::MaxData {}
impl Probing for crate::frame::MaxStreamData {}
impl Probing for crate::frame::MaxStreams {}
impl Probing for crate::frame::NewConnectionId<'_> {
    #[inline]
    fn path_validation(&self) -> Probe {
        Probe::Probing
    }
}
impl Probing for crate::frame::NewToken<'_> {}
impl Probing for crate::frame::Padding {
    #[inline]
    fn path_validation(&self) -> Probe {
        Probe::Probing
    }
}
impl Probing for crate::frame::PathChallenge<'_> {
    #[inline]
    fn path_validation(&self) -> Probe {
        Probe::Probing
    }
}
impl Probing for crate::frame::PathResponse<'_> {
    #[inline]
    fn path_validation(&self) -> Probe {
        Probe::Probing
    }
}
impl Probing for crate::frame::Ping {}
impl Probing for crate::frame::ResetStream {}
impl Probing for crate::frame::RetireConnectionId {}
impl Probing for crate::frame::StopSending {}
impl<Data> Probing for crate::frame::Stream<Data> {}
impl Probing for crate::frame::StreamDataBlocked {}
impl Probing for crate::frame::StreamsBlocked {}

//= https://www.rfc-editor.org/rfc/rfc9000#section-9.1
//= type=test
//# A packet containing only probing frames is a "probing packet", and a
//# packet containing any other frame is a "non-probing packet".
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn probing_packet_test() {
        let mut probe = Probe::Probing;
        probe |= Probe::Probing;

        assert!(probe.is_probing())
    }

    #[test]
    fn probing_and_non_probing_packet_test() {
        let mut probe = Probe::Probing;
        probe |= Probe::NonProbing;

        assert!(!probe.is_probing())
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.2
//# Endpoints can use PING frames (type=0x01) to verify that their peers
//# are still alive or to check reachability to the peer.

macro_rules! ping_tag {
    () => {
        0x01u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.2
//# PING Frame {
//#   Type (i) = 0x01,
//# }

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Ping;

impl Ping {
    pub const fn tag(self) -> u8 {
        ping_tag!()
    }
}

simple_frame_codec!(Ping {}, ping_tag!());


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::varint::VarInt;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.4
//# An endpoint uses a RESET_STREAM frame (type=0x04) to abruptly
//# terminate the sending part of a stream.

macro_rules! reset_stream_tag {
    () => {
        0x04u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.4
//# RESET_STREAM Frame {
//#   Type (i) = 0x04,
//#   Stream ID (i),
//#   Application Protocol Error Code (i),
//#   Final Size (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.4
//# RESET_STREAM frames contain the following fields:
//#
//# Stream ID:  A variable-length integer encoding of the stream ID of
//# the stream being terminated.
//#
//# Application Protocol Error Code:  A variable-length integer
//# containing the application protocol error code (see Section 20.2)
//# that indicates why the stream is being closed.
//#
//# Final Size:  A variable-length integer indicating the final size of
//# the stream by the RESET_STREAM sender, in units of bytes; see
//# Section 4.5.

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ResetStream {
    /// A variable-length integer encoding of the Stream ID of the
    /// stream being terminated.
    pub stream_id: VarInt,

    /// A variable-length integer containing the application protocol
    /// error code which indicates why the stream is being closed.
    pub application_error_code: VarInt,

    /// A variable-length integer indicating the final size of
    /// the stream by the RESET_STREAM sender, in unit of bytes.
    pub final_size: VarInt,
}

impl ResetStream {
    pub const fn tag(&self) -> u8 {
        reset_stream_tag!()
    }
}

simple_frame_codec!(
    ResetStream {
        stream_id,
        application_error_code,
        final_size
    },
    reset_stream_tag!()
);


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::varint::VarInt;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.16
//# An endpoint sends a RETIRE_CONNECTION_ID frame (type=0x19) to
//# indicate that it will no longer use a connection ID that was issued
//# by its peer.

macro_rules! retire_connection_id_tag {
    () => {
        0x19u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.16
//# RETIRE_CONNECTION_ID Frame {
//#   Type (i) = 0x19,
//#   Sequence Number (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.16
//# RETIRE_CONNECTION_ID frames contain the following fields:
//#
//# Sequence Number:  The sequence number of the connection ID being
//#    retired; see Section 5.1.2.

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct RetireConnectionId {
    pub sequence_number: VarInt,
}

impl RetireConnectionId {
    pub const fn tag(self) -> u8 {
        retire_connection_id_tag!()
    }
}

simple_frame_codec!(
    RetireConnectionId { sequence_number },
    retire_connection_id_tag!()
);


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::varint::VarInt;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.5
//# An endpoint uses a STOP_SENDING frame (type=0x05) to communicate that
//# incoming data is being discarded on receipt per application request.
//# STOP_SENDING requests that a peer cease transmission on a stream.

macro_rules! stop_sending_tag {
    () => {
        0x05u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.5
//# STOP_SENDING Frame {
//#   Type (i) = 0x05,
//#   Stream ID (i),
//#   Application Protocol Error Code (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.5
//# STOP_SENDING frames contain the following fields:
//#
//# Stream ID:  A variable-length integer carrying the stream ID of the
//# stream being ignored.
//#
//# Application Protocol Error Code:  A variable-length integer
//# containing the application-specified reason the sender is ignoring
//# the stream; see Section 20.2.

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct StopSending {
    /// A variable-length integer carrying the Stream ID of the
    /// stream being ignored.
    pub stream_id: VarInt,

    /// A variable-length integer containing the application-specified
    /// reason the sender is ignoring the stream
    pub application_error_code: VarInt,
}

impl StopSending {
    pub const fn tag(&self) -> u8 {
        stop_sending_tag!()
    }
}

simple_frame_codec!(
    StopSending {
        stream_id,
        application_error_code
    },
    stop_sending_tag!()
);


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{
    frame::{FitError, Tag},
    varint::VarInt,
};
use core::{convert::TryFrom, mem::size_of};
use s2n_codec::{
    decoder_parameterized_value, DecoderBuffer, DecoderBufferMut, Encoder, EncoderValue,
};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.8
//# STREAM frames implicitly create a stream and carry stream data.  The
//# Type field in the STREAM frame takes the form 0b00001XXX (or the set
//# of values from 0x08 to 0x0f).

macro_rules! stream_tag {
    () => {
        0x08u8..=0x0fu8
    };
}

const STREAM_TAG: u8 = 0x08;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.8
//# *  The OFF bit (0x04) in the frame type is set to indicate that there
//#    is an Offset field present.  When set to 1, the Offset field is
//#    present.  When set to 0, the Offset field is absent and the Stream
//#    Data starts at an offset of 0 (that is, the frame contains the
//#    first bytes of the stream, or the end of a stream that includes no
//#    data).

const OFF_BIT: u8 = 0x04;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.8
//# *  The LEN bit (0x02) in the frame type is set to indicate that there
//#    is a Length field present.  If this bit is set to 0, the Length
//#    field is absent and the Stream Data field extends to the end of
//#    the packet.  If this bit is set to 1, the Length field is present.

const LEN_BIT: u8 = 0x02;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.8
//# *  The FIN bit (0x01) indicates that the frame marks the end of the
//#    stream.  The final size of the stream is the sum of the offset and
//#    the length of this frame.

const FIN_BIT: u8 = 0x01;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.8
//# STREAM Frame {
//#   Type (i) = 0x08..0x0f,
//#   Stream ID (i),
//#   [Offset (i)],
//#   [Length (i)],
//#   Stream Data (..),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.8
//# STREAM frames contain the following fields:
//#
//# Stream ID:  A variable-length integer indicating the stream ID of the
//#    stream; see Section 2.1.
//#
//# Offset:  A variable-length integer specifying the byte offset in the
//#    stream for the data in this STREAM frame.  This field is present
//#    when the OFF bit is set to 1.  When the Offset field is absent,
//#    the offset is 0.
//#
//# Length:  A variable-length integer specifying the length of the
//#    Stream Data field in this STREAM frame.  This field is present
//#    when the LEN bit is set to 1.  When the LEN bit is set to 0, the
//#    Stream Data field consumes all the remaining bytes in the packet.
//#
//# Stream Data:  The bytes from the designated stream to be delivered.

#[derive(Debug, PartialEq, Eq)]
pub struct Stream<Data> {
    /// A variable-length integer indicating the stream ID of the stream
    pub stream_id: VarInt,

    /// A variable-length integer specifying the byte offset in the
    /// stream for the data in this STREAM frame.
    pub offset: VarInt,

    /// If true, the frame is the last frame in the payload
    pub is_last_frame: bool,

    /// If true, the frame marks the end of the stream.
    pub is_fin: bool,

    /// The bytes from the designated stream to be delivered.
    pub data: Data,
}

pub type StreamRef<'a> = Stream<&'a [u8]>;
pub type StreamMut<'a> = Stream<&'a mut [u8]>;

impl<Data> Stream<Data> {
    #[inline]
    pub fn tag(&self) -> u8 {
        let mut tag: u8 = STREAM_TAG;

        if *self.offset != 0 {
            tag |= OFF_BIT;
        }

        if !self.is_last_frame {
            tag |= LEN_BIT;
        }

        if self.is_fin {
            tag |= FIN_BIT;
        }

        tag
    }

    /// Converts the stream data from one type to another
    #[inline]
    pub fn map_data<F: FnOnce(Data) -> Out, Out>(self, map: F) -> Stream<Out> {
        Stream {
            stream_id: self.stream_id,
            offset: self.offset,
            is_last_frame: self.is_last_frame,
            is_fin: self.is_fin,
            data: map(self.data),
        }
    }
}

impl<Data: EncoderValue> Stream<Data> {
    /// Tries to fit the frame into the provided capacity
    ///
    /// The `is_last_frame` field will be updated with this call.
    ///
    /// If ok, the new payload length is returned, otherwise the frame cannot
    /// fit.
    #[inline]
    pub fn try_fit(&mut self, capacity: usize) -> Result<usize, FitError> {
        let mut fixed_len = 0;
        fixed_len += size_of::<Tag>();
        fixed_len += self.stream_id.encoding_size();

        if self.offset != 0u64 {
            fixed_len += self.offset.encoding_size();
        }

        let remaining_capacity = capacity.checked_sub(fixed_len).ok_or(FitError)?;

        let data_len = self.data.encoding_size();
        let max_data_len = remaining_capacity.min(data_len);

        // If data fits exactly into the capacity, mark it as the last frame
        if max_data_len == remaining_capacity {
            self.is_last_frame = true;
            return Ok(max_data_len);
        }

        self.is_last_frame = false;

        // Compute the maximum length prefix size we would need
        let len_prefix_size = VarInt::try_from(max_data_len)
            .map_err(|_| FitError)?
            .encoding_size();

        // Subtract the maximum length prefix size from the remaining capacity
        //
        // NOTE: It's possible that this result isn't completely optimal in every case. However,
        //       instead of spending extra cycles fitting a couple of bytes into the frame, it's
        //       good enough in most cases.
        let prefixed_data_len = remaining_capacity
            .checked_sub(len_prefix_size)
            .ok_or(FitError)?;

        let data_len = prefixed_data_len.min(data_len);

        Ok(data_len)
    }
}

decoder_parameterized_value!(
    impl<'a, Data> Stream<Data> {
        fn decode(tag: Tag, buffer: Buffer) -> Result<Self> {
            let has_offset = tag & OFF_BIT == OFF_BIT;
            let is_last_frame = tag & LEN_BIT != LEN_BIT;
            let is_fin = tag & FIN_BIT == FIN_BIT;

            let (stream_id, buffer) = buffer.decode()?;

            let (offset, buffer) = if has_offset {
                buffer.decode()?
            } else {
                (Default::default(), buffer)
            };

            let (data, buffer) = if !is_last_frame {
                let (data, buffer) = buffer.decode_with_len_prefix::<VarInt, Data>()?;
                (data, buffer)
            } else {
                let len = buffer.len();
                let (data, buffer) = buffer.decode_slice(len)?;
                let (data, remaining) = data.decode()?;
                remaining.ensure_empty()?;
                (data, buffer)
            };

            let frame = Stream {
                stream_id,
                offset,
                is_last_frame,
                is_fin,
                data,
            };

            Ok((frame, buffer))
        }
    }
);

impl<Data: EncoderValue> EncoderValue for Stream<Data> {
    #[inline]
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());
        buffer.encode(&self.stream_id);

        if *self.offset != 0 {
            buffer.encode(&self.offset);
        }

        if self.is_last_frame {
            buffer.encode(&self.data);
        } else {
            buffer.encode_with_len_prefix::<VarInt, _>(&self.data);
        }
    }

    /// We hand optimize this encoding size so we can quickly estimate
    /// how large a STREAM frame will be
    #[inline]
    fn encoding_size_for_encoder<E: Encoder>(&self, encoder: &E) -> usize {
        let mut len = 0;
        len += size_of::<Tag>();
        len += self.stream_id.encoding_size();

        if *self.offset != 0 {
            len += self.offset.encoding_size();
        }

        let data_len = self.data.encoding_size_for_encoder(encoder);
        len += data_len;

        // include the len prefix
        if !self.is_last_frame {
            len += VarInt::try_from(data_len).unwrap().encoding_size();
        }

        // make sure the encoding size matches what we would actually encode
        if cfg!(debug_assertions) {
            use s2n_codec::EncoderLenEstimator;

            let mut estimator = EncoderLenEstimator::new(encoder.remaining_capacity());
            self.encode(&mut estimator);
            assert_eq!(estimator.len(), len);
        }

        len
    }
}

impl<'a> From<Stream<DecoderBuffer<'a>>> for StreamRef<'a> {
    #[inline]
    fn from(s: Stream<DecoderBuffer<'a>>) -> Self {
        s.map_data(|data| data.into_less_safe_slice())
    }
}

impl<'a> From<Stream<DecoderBufferMut<'a>>> for StreamRef<'a> {
    #[inline]
    fn from(s: Stream<DecoderBufferMut<'a>>) -> Self {
        s.map_data(|data| &*data.into_less_safe_slice())
    }
}

impl<'a> From<Stream<DecoderBufferMut<'a>>> for StreamMut<'a> {
    #[inline]
    fn from(s: Stream<DecoderBufferMut<'a>>) -> Self {
        s.map_data(|data| data.into_less_safe_slice())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::frame::Padding;
    use bolero::check;
    use core::convert::TryInto;

    fn model(stream_id: VarInt, offset: VarInt, length: VarInt, capacity: usize) {
        let length = if let Ok(length) = VarInt::try_into(length) {
            length
        } else {
            // if the length cannot be represented by `usize` then bail
            return;
        };

        let mut frame = Stream {
            stream_id,
            offset,
            is_last_frame: false,
            is_fin: false,
            data: Padding { length },
        };

        if let Ok(new_length) = frame.try_fit(capacity) {
            frame.data = Padding { length: new_length };

            // we should never exceed the capacity
            assert!(
                frame.encoding_size() <= capacity,
                "the encoding_size should not exceed capacity {:#?}",
                frame
            );

            if new_length < length {
                let mut min = capacity;

                // allow the payload to be smaller by the encoding size of the length prefix
                if !frame.is_last_frame {
                    min -= VarInt::try_from(new_length).unwrap().encoding_size();
                }

                // the payload was trimmed so we should be at capacity
                let max = capacity;

                assert!(
                    (min..=max).contains(&frame.encoding_size()),
                    "encoding_size ({}) should match capacity ({capacity}) {frame:#?}",
                    frame.encoding_size(),
                );
            }

            if frame.is_last_frame {
                // the `is_last_frame` should _only_ be set when the encoding size == capacity
                assert_eq!(
                    frame.encoding_size(),
                    capacity,
                    "should only be the last frame if == capacity {:#?}",
                    frame
                );
            }
        } else {
            assert!(
                frame.encoding_size() > capacity,
                "rejection should only occur when encoding size > capacity {:#?}",
                frame
            );
        }
    }

    #[test]
    #[cfg_attr(kani, kani::proof, kani::unwind(1), kani::solver(kissat))]
    fn try_fit_test() {
        check!()
            .with_type()
            .cloned()
            .for_each(|(stream_id, offset, length, capacity)| {
                model(stream_id, offset, length, capacity);
            });
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{frame::Tag, stream::StreamType, varint::VarInt};
use s2n_codec::{decoder_invariant, decoder_parameterized_value, Encoder, EncoderValue};

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.14
//# A STREAMS_BLOCKED
//# frame of type 0x16 is used to indicate reaching the bidirectional
//# stream limit, and a STREAMS_BLOCKED frame of type 0x17 is used to
//# indicate reaching the unidirectional stream limit.

macro_rules! streams_blocked_tag {
    () => {
        0x16u8..=0x17u8
    };
}
const BIDIRECTIONAL_TAG: u8 = 0x16;
const UNIDIRECTIONAL_TAG: u8 = 0x17;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.14
//# STREAMS_BLOCKED Frame {
//#   Type (i) = 0x16..0x17,
//#   Maximum Streams (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.14
//# STREAMS_BLOCKED frames contain the following field:
//#
//# Maximum Streams:  A variable-length integer indicating the maximum
//#    number of streams allowed at the time the frame was sent.

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct StreamsBlocked {
    pub stream_type: StreamType,

    /// A variable-length integer indicating the stream limit at the
    /// time the frame was sent.
    pub stream_limit: VarInt,
}

impl StreamsBlocked {
    pub fn tag(&self) -> u8 {
        match self.stream_type {
            StreamType::Bidirectional => BIDIRECTIONAL_TAG,
            StreamType::Unidirectional => UNIDIRECTIONAL_TAG,
        }
    }
}

decoder_parameterized_value!(
    impl<'a> StreamsBlocked {
        fn decode(tag: Tag, buffer: Buffer) -> Result<Self> {
            let stream_type = if BIDIRECTIONAL_TAG == tag {
                StreamType::Bidirectional
            } else {
                StreamType::Unidirectional
            };

            let (stream_limit, buffer) = buffer.decode::<VarInt>()?;

            //= https://www.rfc-editor.org/rfc/rfc9000#section-19.14
            //# This
            //# value cannot exceed 2^60, as it is not possible to encode stream
            //# IDs larger than 2^62-1.  Receipt of a frame that encodes a larger
            //# stream ID MUST be treated as a connection error of type
            //# STREAM_LIMIT_ERROR or FRAME_ENCODING_ERROR.
            decoder_invariant!(
                *stream_limit <= 2u64.pow(60),
                "maximum streams cannot exceed 2^60"
            );

            let frame = StreamsBlocked {
                stream_type,
                stream_limit,
            };

            Ok((frame, buffer))
        }
    }
);

impl EncoderValue for StreamsBlocked {
    fn encode<E: Encoder>(&self, buffer: &mut E) {
        buffer.encode(&self.tag());
        buffer.encode(&self.stream_limit);
    }
}


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::varint::VarInt;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.13
//# This frame is analogous to DATA_BLOCKED (Section 19.12).

macro_rules! stream_data_blocked_tag {
    () => {
        0x15u8
    };
}

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.13
//# STREAM_DATA_BLOCKED Frame {
//#   Type (i) = 0x15,
//#   Stream ID (i),
//#   Maximum Stream Data (i),
//# }

//= https://www.rfc-editor.org/rfc/rfc9000#section-19.13
//# STREAM_DATA_BLOCKED frames contain the following fields:
//#
//# Stream ID:  A variable-length integer indicating the stream that is
//#    blocked due to flow control.
//#
//# Maximum Stream Data:  A variable-length integer indicating the offset
//#    of the stream at which the blocking occurred.

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct StreamDataBlocked {
    /// A variable-length integer indicating the stream which
    /// is flow control blocked.
    pub stream_id: VarInt,

    /// A variable-length integer indicating the offset of the stream at
    // which the blocking occurred.
    pub stream_data_limit: VarInt,
}

impl StreamDataBlocked {
    pub const fn tag(&self) -> u8 {
        stream_data_blocked_tag!()
    }
}

simple_frame_codec!(
    StreamDataBlocked {
        stream_id,
        stream_data_limit
    },
    stream_data_blocked_tag!()
);


// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::frame::FrameRef;
use bolero::check;
use s2n_codec::{assert_codec_round_trip_bytes_mut, Encoder, EncoderLenEstimator, EncoderValue};

#[test]
fn round_trip() {
    check!().for_each(|input| {
        let mut input = input.to_vec();
        let frames = assert_codec_round_trip_bytes_mut!(FrameRef, &mut input);

        for frame in frames {
            // make sure the frames encoding size matches what would actually
            // be written to an encoder
            let mut estimator = EncoderLenEstimator::new(core::usize::MAX);
            frame.encode(&mut estimator);
            assert_eq!(frame.encoding_size(), estimator.len());
        }
    });
}