|
1 | 1 | use bitvec::prelude::*;
|
2 | 2 | use parity_scale_codec::{Decode, Encode};
|
3 | 3 | use rayon::prelude::*;
|
| 4 | +use std::mem::ManuallyDrop; |
4 | 5 | use std::ops::{Deref, DerefMut};
|
5 | 6 | use std::{mem, slice};
|
6 | 7 | use subspace_core_primitives::checksum::Blake3Checksummed;
|
@@ -59,24 +60,24 @@ pub struct SectorMetadata {
|
59 | 60 | impl SectorMetadata {
|
60 | 61 | /// Returns offsets of each s-bucket relatively to the beginning of the sector (in chunks)
|
61 | 62 | pub fn s_bucket_offsets(&self) -> Box<[u32; Record::NUM_S_BUCKETS]> {
|
62 |
| - // TODO: Should have been just `::new()`, but https://github.com/rust-lang/rust/issues/53827 |
63 |
| - // SAFETY: Data structure filled with zeroes is a valid invariant |
64 |
| - let mut s_bucket_offsets = |
65 |
| - unsafe { Box::<[u32; Record::NUM_S_BUCKETS]>::new_zeroed().assume_init() }; |
66 |
| - |
67 |
| - self.s_bucket_sizes |
| 63 | + let s_bucket_offsets = self |
| 64 | + .s_bucket_sizes |
68 | 65 | .iter()
|
69 |
| - .zip(s_bucket_offsets.iter_mut()) |
70 |
| - .for_each({ |
| 66 | + .map({ |
71 | 67 | let mut base_offset = 0;
|
72 | 68 |
|
73 |
| - move |(s_bucket_size, s_bucket_offset)| { |
74 |
| - *s_bucket_offset = base_offset; |
| 69 | + move |s_bucket_size| { |
| 70 | + let offset = base_offset; |
75 | 71 | base_offset += u32::from(*s_bucket_size);
|
| 72 | + offset |
76 | 73 | }
|
77 |
| - }); |
| 74 | + }) |
| 75 | + .collect::<Box<_>>(); |
78 | 76 |
|
79 |
| - s_bucket_offsets |
| 77 | + assert_eq!(s_bucket_offsets.len(), Record::NUM_S_BUCKETS); |
| 78 | + let mut s_bucket_offsets = ManuallyDrop::new(s_bucket_offsets); |
| 79 | + // SAFETY: Original memory is not dropped, number of elements checked above |
| 80 | + unsafe { Box::from_raw(s_bucket_offsets.as_mut_ptr() as *mut [u32; Record::NUM_S_BUCKETS]) } |
80 | 81 | }
|
81 | 82 | }
|
82 | 83 |
|
@@ -164,6 +165,7 @@ impl RawSector {
|
164 | 165 |
|
165 | 166 | // Bit array containing space for bits equal to the number of s-buckets in a record
|
166 | 167 | type SingleRecordBitArray = BitArray<[u8; Record::NUM_S_BUCKETS / u8::BITS as usize]>;
|
| 168 | + |
167 | 169 | const SINGLE_RECORD_BIT_ARRAY_SIZE: usize = mem::size_of::<SingleRecordBitArray>();
|
168 | 170 |
|
169 | 171 | // TODO: I really tried to avoid `count_ones()`, but wasn't able to with safe Rust due to lifetimes
|
@@ -400,23 +402,21 @@ impl SectorContentsMap {
|
400 | 402 |
|
401 | 403 | /// Returns sizes of each s-bucket
|
402 | 404 | pub fn s_bucket_sizes(&self) -> Box<[u16; Record::NUM_S_BUCKETS]> {
|
403 |
| - // TODO: Should have been just `::new()`, but https://github.com/rust-lang/rust/issues/53827 |
404 |
| - // SAFETY: Data structure filled with zeroes is a valid invariant |
405 |
| - let mut s_bucket_sizes = |
406 |
| - unsafe { Box::<[u16; Record::NUM_S_BUCKETS]>::new_zeroed().assume_init() }; |
407 | 405 | // Rayon doesn't support iteration over custom types yet
|
408 |
| - (u16::from(SBucket::ZERO)..=u16::from(SBucket::MAX)) |
| 406 | + let s_bucket_sizes = (u16::from(SBucket::ZERO)..=u16::from(SBucket::MAX)) |
409 | 407 | .into_par_iter()
|
410 | 408 | .map(SBucket::from)
|
411 |
| - .zip(s_bucket_sizes.par_iter_mut()) |
412 |
| - .for_each(|(s_bucket, s_bucket_size)| { |
413 |
| - *s_bucket_size = self |
414 |
| - .iter_s_bucket_records(s_bucket) |
| 409 | + .map(|s_bucket| { |
| 410 | + self.iter_s_bucket_records(s_bucket) |
415 | 411 | .expect("S-bucket guaranteed to be in range; qed")
|
416 |
| - .count() as u16; |
417 |
| - }); |
| 412 | + .count() as u16 |
| 413 | + }) |
| 414 | + .collect::<Box<_>>(); |
418 | 415 |
|
419 |
| - s_bucket_sizes |
| 416 | + assert_eq!(s_bucket_sizes.len(), Record::NUM_S_BUCKETS); |
| 417 | + let mut s_bucket_sizes = ManuallyDrop::new(s_bucket_sizes); |
| 418 | + // SAFETY: Original memory is not dropped, number of elements checked above |
| 419 | + unsafe { Box::from_raw(s_bucket_sizes.as_mut_ptr() as *mut [u16; Record::NUM_S_BUCKETS]) } |
420 | 420 | }
|
421 | 421 |
|
422 | 422 | /// Creates an iterator of `(s_bucket, encoded_chunk_used, chunk_location)`, where `s_bucket` is
|
|
0 commit comments