diff --git a/src/file/chunk.rs b/src/file/chunk.rs index a2d2eb0..0c22124 100644 --- a/src/file/chunk.rs +++ b/src/file/chunk.rs @@ -1,4 +1,4 @@ -use std::fmt; +use std::{any, fmt}; use crate::sharry; @@ -23,6 +23,22 @@ impl fmt::Debug for Chunk<'_> { } } +/// convert usize into other type +/// +/// # Panics +/// +/// - if the given value does not fit into the target type +fn from_usize_or_panic(value: usize) -> I +where + I: TryFrom, + I::Error: std::error::Error, +{ + value.try_into().unwrap_or_else(|e| { + let target_type = any::type_name::(); + panic!("usize={value:?} did not fit into {target_type:?}: {e}") + }) +} + impl<'t> Chunk<'t> { pub(super) fn new_direct(file_id: sharry::FileID, offset: u64, data: &'t [u8]) -> Self { Self { @@ -49,12 +65,10 @@ impl<'t> Chunk<'t> { /// get the chunk's length pub fn get_length(&self) -> u64 { - let len = self.data.len(); - - // BOOKMARK this might **panic** on platforms where `usize` has more than 64 bit. + // BOOKMARK this might **panic** on (hypothetical) platforms where `usize` has more than 64 bit. // Also, you've allocated more than 2 EiB ... in ONE chunk. // Whoa! Maybe just chill? - u64::try_from(len).unwrap_or_else(|e| panic!("usize={len} did not fit into u64: {e}")) + from_usize_or_panic(self.data.len()) } } @@ -90,4 +104,17 @@ mod tests { assert_eq!(chunk.get_length(), len); } } + + #[test] + #[should_panic(expected = "did not fit into \"u32\"")] + fn test_usize_overflow_panics() { + // works + assert_eq!(from_usize_or_panic::(usize::MAX), u64::MAX); + assert_eq!(from_usize_or_panic::(u32::MAX as usize), u32::MAX); + assert_eq!(from_usize_or_panic::(u16::MAX as usize), u16::MAX); + assert_eq!(from_usize_or_panic::(u8::MAX as usize), u8::MAX); + + // panics + from_usize_or_panic::(usize::MAX); + } }