use std::fmt;
use std::fmt::Debug;
use std::fmt::Write as _;
pub(in crate::domain) fn bounded_debug<T>(value: &T, maximum: usize) -> (String, bool)
where
T: Debug + ?Sized,
{
let mut writer = BoundedCapture::new(maximum);
let _ = write!(&mut writer, "{value:?}");
writer.finish()
}
struct BoundedCapture {
output: String,
maximum: usize,
truncated: bool,
}
impl BoundedCapture {
#[must_use]
#[inline(always)]
fn new(maximum: usize) -> Self {
Self {
output: String::new(),
maximum,
truncated: false,
}
}
#[must_use]
#[inline(always)]
fn finish(self) -> (String, bool) {
(self.output, self.truncated)
}
}
impl fmt::Write for BoundedCapture {
#[inline]
fn write_str(&mut self, value: &str) -> fmt::Result {
if self.truncated || value.len() > self.maximum.saturating_sub(self.output.len()) {
self.truncated = true;
return Err(fmt::Error);
}
self.output.push_str(value);
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::fmt::Write;
use super::BoundedCapture;
#[test]
fn test_rejected_debug_chunk_closes_capture_permanently() {
let mut capture = BoundedCapture::new(4);
assert!(capture.write_str("oversized").is_err());
assert!(capture.write_str("x").is_err());
let (text, truncated) = capture.finish();
assert!(text.is_empty());
assert!(truncated);
}
}