From cdea09258c8a640735d4558db799a3fa2dbd72b7 Mon Sep 17 00:00:00 2001 From: Marshall Pierce <575695+marshallpierce@users.noreply.github.com> Date: Wed, 1 Jul 2026 06:55:56 -0600 Subject: [PATCH] Remove all `unsafe` usage Fixes #136. The unsafe usage in V2Serializer was only worth maybe ~5% speedup, assuming it was correct, which it was not... Past me did not worry enough about unsafe, apparently. --- CHANGELOG.md | 1 + src/lib.rs | 1 + src/serialization/v2_serializer.rs | 15 +++++---------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e74b110..899ccc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Added ### Changed + - All usages of `unsafe` are removed, causing serialization to be slightly slower, but safe. ### Removed diff --git a/src/lib.rs b/src/lib.rs index e3a4e4b..869ac43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -194,6 +194,7 @@ unused_results, variant_size_differences )] +#![forbid(unsafe_code)] // Enable feature(test) is enabled so that we can have benchmarks of private code #![cfg_attr(all(test, feature = "bench_private"), feature(test))] diff --git a/src/serialization/v2_serializer.rs b/src/serialization/v2_serializer.rs index 1607154..313cbff 100644 --- a/src/serialization/v2_serializer.rs +++ b/src/serialization/v2_serializer.rs @@ -93,11 +93,8 @@ impl Serializer for V2Serializer { debug_assert_eq!(V2_HEADER_SIZE, self.buf.len()); - unsafe { - // want to treat the rest of the vec as a slice, and we've already reserved this - // space, so this way we don't have to resize() on a lot of dummy bytes. - self.buf.set_len(max_size); - } + // want to treat the rest of the vec as a slice + self.buf.resize(max_size, 0); let counts_len = encode_counts(h, &mut self.buf[V2_HEADER_SIZE..])?; // addition should be safe as max_size is already a usize @@ -142,11 +139,11 @@ pub fn encode_counts( let mut index = 0; let mut bytes_written = 0; - assert!(index_limit <= h.counts.len()); + assert!(index_limit < h.counts.len()); while index <= index_limit { // index is inside h.counts because of the assert above - let count = unsafe { *(h.counts.get_unchecked(index)) }; + let count = h.counts[index]; index += 1; // Non-negative values are counts for the respective value, negative values are skipping @@ -157,9 +154,7 @@ pub fn encode_counts( zero_count = 1; // index is inside h.counts because of the assert above - while (index <= index_limit) - && (unsafe { *(h.counts.get_unchecked(index)) } == T::zero()) - { + while (index <= index_limit) && h.counts[index] == T::zero() { zero_count += 1; index += 1; }