use std::fmt;
use super::BodyCaptureError;
#[must_use]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct BodyCapture<'a> {
bytes: &'a [u8],
total_len: Option<usize>,
source_truncated: bool,
}
impl fmt::Debug for BodyCapture<'_> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("BodyCapture")
.field("bytes", &"<redacted>")
.field("captured_len", &self.bytes.len())
.field("total_len", &self.total_len)
.field("omitted_len", &self.omitted_len())
.field("source_truncated", &self.source_truncated)
.finish()
}
}
impl<'a> BodyCapture<'a> {
pub const fn complete(bytes: &'a [u8]) -> Self {
Self {
bytes,
total_len: Some(bytes.len()),
source_truncated: false,
}
}
#[inline]
pub fn prefix(bytes: &'a [u8], max_bytes: usize) -> Self {
let captured_len = bytes.len().min(max_bytes);
if captured_len == bytes.len() {
Self::complete(bytes)
} else {
Self {
bytes: &bytes[..captured_len],
total_len: Some(bytes.len()),
source_truncated: true,
}
}
}
pub const fn truncated_unknown(bytes: &'a [u8]) -> Self {
Self {
bytes,
total_len: None,
source_truncated: true,
}
}
#[inline]
pub const fn truncated(
bytes: &'a [u8],
total_len: Option<usize>,
) -> Result<Self, BodyCaptureError> {
if let Some(total) = total_len
&& total <= bytes.len()
{
return Err(BodyCaptureError::InvalidTotalLength {
captured: bytes.len(),
total,
});
}
Ok(Self {
bytes,
total_len,
source_truncated: true,
})
}
#[inline(always)]
pub const fn bytes(self) -> &'a [u8] {
self.bytes
}
#[must_use]
#[inline(always)]
pub const fn captured_len(self) -> usize {
self.bytes.len()
}
#[inline(always)]
pub const fn total_len(self) -> Option<usize> {
self.total_len
}
#[inline(always)]
pub const fn omitted_len(self) -> Option<usize> {
match self.total_len {
Some(total) => Some(total - self.bytes.len()),
None => None,
}
}
#[must_use]
#[inline(always)]
pub const fn is_source_truncated(self) -> bool {
self.source_truncated
}
}