stream-transfer-limit 0.1.0

Byte-count transfer limits for fallible futures streams
Documentation
use thiserror::Error;

/// Error returned by a transfer-limited stream.
#[derive(Debug, Error)]
pub enum TransferLimitError<E, C = usize> {
    /// The stream produced more bytes than allowed.
    #[error("transfer size limit exceeded: observed {actual} bytes with a {limit} byte limit")]
    LimitExceeded {
        /// Configured maximum number of bytes.
        limit: C,
        /// Number of bytes observed after reading the chunk that crossed the limit.
        actual: C,
    },
    /// The cumulative byte count cannot be represented by the selected counter.
    #[error(
        "transfer counter overflowed after {bytes_seen} bytes while adding a {chunk_len} byte chunk"
    )]
    CounterOverflow {
        /// Number of bytes counted before reading the chunk that overflowed.
        bytes_seen: C,
        /// Byte length of the chunk that could not be added to the counter.
        chunk_len: usize,
    },
    /// The wrapped stream returned an error.
    #[error("inner stream returned an error")]
    Inner {
        /// Original stream error.
        #[source]
        source: E,
    },
}

impl<E, C> TransferLimitError<E, C> {
    /// Returns `true` when this error represents an exceeded transfer limit.
    pub fn is_limit_exceeded(&self) -> bool {
        matches!(self, Self::LimitExceeded { .. })
    }

    /// Returns `true` when the selected counter type could not represent the
    /// cumulative byte count.
    pub fn is_counter_overflow(&self) -> bool {
        matches!(self, Self::CounterOverflow { .. })
    }

    /// Returns the wrapped stream error, if this is an inner stream error.
    pub fn into_inner(self) -> Option<E> {
        match self {
            Self::Inner { source } => Some(source),
            Self::LimitExceeded { .. } | Self::CounterOverflow { .. } => None,
        }
    }

    pub(crate) fn inner(source: E) -> Self {
        Self::Inner { source }
    }
}

impl<E, C> From<E> for TransferLimitError<E, C> {
    fn from(source: E) -> Self {
        Self::inner(source)
    }
}