diff --git a/CHANGELOG.md b/CHANGELOG.md index 02258af49..243213ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +- Replaced 6 in-function-invariant `.expect()` sites in `lading_payload` + with `.unwrap_or_else(|_| unreachable!("..."))` / + `.unwrap_or_else(|| unreachable!("..."))`. Covered: `usize → u32` + conversions in `block::construct_block`, + `random_string_pool::of_size_with_handle` (×2), and + `string_list_pool::range_value_at` (×2, plus one + `char::from_u32(...)` on values produced by char range expansion). + All sites are guarded by invariants established earlier in the same + function or at pool construction (`with_size` asserts pool length + fits in u32). No runtime behavior change. - Replaced 5 additional infallible-by-construction `.expect()` sites in `lading_payload` with `.unwrap_or_else(|_| unreachable!("..."))` / `.unwrap_or_else(|| unreachable!("..."))`. Covered: 4 sites in diff --git a/lading_payload/src/block.rs b/lading_payload/src/block.rs index bbf6be576..62e2b0327 100644 --- a/lading_payload/src/block.rs +++ b/lading_payload/src/block.rs @@ -745,12 +745,9 @@ where // serializer. Err(SpinError::EmptyBlock) } else { - let total_bytes = NonZeroU32::new( - bytes - .len() - .try_into() - .expect("failed to get length of bytes"), - ) + let total_bytes = NonZeroU32::new(bytes.len().try_into().unwrap_or_else(|_| { + unreachable!("bytes.len() fits in u32: blocks are sized by chunk_size: u32") + })) .ok_or(SpinError::Zero)?; let mut metadata = BlockMetadata::default(); diff --git a/lading_payload/src/common/strings/random_string_pool.rs b/lading_payload/src/common/strings/random_string_pool.rs index b168b5213..b07bb7f2a 100644 --- a/lading_payload/src/common/strings/random_string_pool.rs +++ b/lading_payload/src/common/strings/random_string_pool.rs @@ -122,8 +122,10 @@ impl Pool for RandomStringPool { Handle::PosAndLength( lower_idx .try_into() - .expect("must fit into u32 by construction"), - bytes.try_into().expect("must fit in u32 by construction"), + .unwrap_or_else(|_| unreachable!("lower_idx < self.inner.len(), and self.inner.len() fits in u32 by the assert in with_size")), + bytes + .try_into() + .unwrap_or_else(|_| unreachable!("bytes < self.inner.len(), and self.inner.len() fits in u32 by the assert in with_size")), ), )) } diff --git a/lading_payload/src/common/strings/string_list_pool.rs b/lading_payload/src/common/strings/string_list_pool.rs index 798a60484..967eb2135 100644 --- a/lading_payload/src/common/strings/string_list_pool.rs +++ b/lading_payload/src/common/strings/string_list_pool.rs @@ -250,13 +250,21 @@ fn range_len(range: &PatternRange) -> Result { fn range_value_at(range: &PatternRange, idx: usize) -> String { match range { PatternRange::Char(start, _end) => char::from_u32( - *start as u32 + u32::try_from(idx).expect("pattern shouldn't be that big"), + *start as u32 + + u32::try_from(idx).unwrap_or_else(|_| { + unreachable!("idx is bounded by range length, which fits in u32") + }), ) - .expect("idx is within range bounds") + .unwrap_or_else(|| { + unreachable!("char range expansion produces valid Unicode scalars by construction") + }) .to_string(), PatternRange::Number(start, end) => { let numdigits = std::cmp::max(start.to_string().len(), end.to_string().len()); - let n = start + u32::try_from(idx).expect("pattern shouldn't be that big"); + let n = start + + u32::try_from(idx).unwrap_or_else(|_| { + unreachable!("idx is bounded by range length, which fits in u32") + }); format!("{n:0numdigits$}") } }