From 72361cb98dffa77d64610759e69273d0e7e443cb Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Tue, 19 Nov 2024 20:34:16 -0500 Subject: [PATCH] Add Integer::MAX_STR_LEN and use it to tell the compiler about the max buffer size --- src/lib.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1eeb86b..88d92ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,17 +95,24 @@ impl Buffer { /// representation within the buffer. #[cfg_attr(feature = "no-panic", no_panic)] pub fn format(&mut self, i: I) -> &str { - i.write(unsafe { + let str = i.write(unsafe { &mut *(&mut self.bytes as *mut [MaybeUninit; I128_MAX_LEN] as *mut ::Buffer) - }) + }); + if str.len() > I::MAX_STR_LEN { + unsafe { core::hint::unreachable_unchecked() } + } + str } } /// An integer that can be written into an [`itoa::Buffer`][Buffer]. /// /// This trait is sealed and cannot be implemented for types outside of itoa. -pub trait Integer: private::Sealed {} +pub trait Integer: private::Sealed { + /// The maximum length of the formated str for this integer. + const MAX_STR_LEN: usize; +} // Seal to prevent downstream implementations of the Integer trait. mod private { @@ -126,7 +133,9 @@ const DEC_DIGITS_LUT: &[u8] = b"\ // https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266 macro_rules! impl_Integer { ($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$( - impl Integer for $t {} + impl Integer for $t { + const MAX_STR_LEN: usize = $max_len; + } impl private::Sealed for $t { type Buffer = [MaybeUninit; $max_len]; @@ -236,7 +245,9 @@ impl_Integer!(I64_MAX_LEN => isize, U64_MAX_LEN => usize as u64); macro_rules! impl_Integer128 { ($($max_len:expr => $t:ident),*) => {$( - impl Integer for $t {} + impl Integer for $t { + const MAX_STR_LEN: usize = $max_len; + } impl private::Sealed for $t { type Buffer = [MaybeUninit; $max_len];