Вы не можете сделать это без фактического выполнения форматирования. Форматирование по умолчанию ленив, и у черт форматирования нет метода, который позволяет запрашивать, какой размер будет.
Кроме того, реализация типа Debug::fmt
может выделять или не распределять, поэтому невозможно сказать, что нет распределение произойдет.
Самое простое, что нужно сделать, это создать строку и вернуть длину строки:
fn width(to_print_later: &impl std::fmt::Debug) -> usize {
format!("{:?}", to_print_later).len()
}
Если вы хотите избежать своего собственного Вы можете написать свой собственный реализатор fmt::Write
и отформатировать его, считая только длину:
use std::fmt::{self, Write};
fn width(to_print_later: &impl fmt::Debug) -> usize {
let mut c = CountingWriter::default();
write!(&mut c, "{:?}", to_print_later).expect("Exceeded the usize");
c.0
}
#[derive(Debug, Default)]
struct CountingWriter(usize);
impl fmt::Write for CountingWriter {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.0 = usize::checked_add(self.0, s.len()).ok_or(fmt::Error)?;
Ok(())
}
}
Это не является гарантированным выигрышем в производительности, поскольку возможно, что реализация Debug::fmt
это тяжелая часть, а не распределение. Как обычно, профиль, чтобы знать, что лучше для вашего случая.
Обратите внимание, что я использую Debug
в этом ответе, но это относится и к другим чертам, таким как Display
и LowerHex
.