Skip to main content

subspace_core_primitives/
pieces.rs

1//! Pieces-related data structures.
2
3#[cfg(not(feature = "std"))]
4extern crate alloc;
5
6use crate::ScalarBytes;
7use crate::segments::{ArchivedHistorySegment, RecordedHistorySegment, SegmentIndex};
8#[cfg(feature = "serde")]
9use ::serde::{Deserialize, Serialize};
10#[cfg(feature = "serde")]
11use ::serde::{Deserializer, Serializer};
12#[cfg(not(feature = "std"))]
13use alloc::boxed::Box;
14#[cfg(not(feature = "std"))]
15use alloc::format;
16#[cfg(not(feature = "std"))]
17use alloc::vec::Vec;
18use bytes::{Bytes, BytesMut};
19use core::array::TryFromSliceError;
20use core::hash::{Hash, Hasher};
21use core::iter::Step;
22use core::{fmt, mem, slice};
23use derive_more::with_trait::{
24    Add, AddAssign, AsMut, AsRef, Deref, DerefMut, Display, Div, DivAssign, From, Into, Mul,
25    MulAssign, Sub, SubAssign,
26};
27use parity_scale_codec::{
28    Decode, DecodeWithMemTracking, Encode, EncodeLike, Input, MaxEncodedLen, Output,
29};
30#[cfg(feature = "parallel")]
31use rayon::prelude::*;
32use scale_info::build::Fields;
33use scale_info::{Path, Type, TypeInfo};
34#[cfg(feature = "serde")]
35use serde_big_array::BigArray;
36
37/// Piece index in consensus
38#[derive(
39    Debug,
40    Display,
41    Default,
42    Copy,
43    Clone,
44    Ord,
45    PartialOrd,
46    Eq,
47    PartialEq,
48    Hash,
49    Encode,
50    Decode,
51    Add,
52    AddAssign,
53    Sub,
54    SubAssign,
55    Mul,
56    MulAssign,
57    Div,
58    DivAssign,
59    TypeInfo,
60    MaxEncodedLen,
61)]
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63#[repr(transparent)]
64pub struct PieceIndex(u64);
65
66impl Step for PieceIndex {
67    #[inline]
68    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
69        u64::steps_between(&start.0, &end.0)
70    }
71
72    #[inline]
73    fn forward_checked(start: Self, count: usize) -> Option<Self> {
74        u64::forward_checked(start.0, count).map(Self)
75    }
76
77    #[inline]
78    fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
79        let (n, overflowing) = u64::forward_overflowing(start.0, count);
80        (Self(n), overflowing)
81    }
82
83    #[inline]
84    fn backward_checked(start: Self, count: usize) -> Option<Self> {
85        u64::backward_checked(start.0, count).map(Self)
86    }
87
88    #[inline]
89    fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
90        let (n, overflowing) = u64::backward_overflowing(start.0, count);
91        (Self(n), overflowing)
92    }
93}
94
95impl From<u64> for PieceIndex {
96    #[inline]
97    fn from(original: u64) -> Self {
98        Self(original)
99    }
100}
101
102impl From<PieceIndex> for u64 {
103    #[inline]
104    fn from(original: PieceIndex) -> Self {
105        original.0
106    }
107}
108
109impl PieceIndex {
110    /// Size in bytes.
111    pub const SIZE: usize = mem::size_of::<u64>();
112    /// Piece index 0.
113    pub const ZERO: PieceIndex = PieceIndex(0);
114    /// Piece index 1.
115    pub const ONE: PieceIndex = PieceIndex(1);
116
117    /// Create new instance
118    #[inline]
119    pub const fn new(n: u64) -> Self {
120        Self(n)
121    }
122
123    /// Create piece index from bytes.
124    #[inline]
125    pub const fn from_bytes(bytes: [u8; Self::SIZE]) -> Self {
126        Self(u64::from_le_bytes(bytes))
127    }
128
129    /// Convert piece index to bytes.
130    #[inline]
131    pub const fn to_bytes(self) -> [u8; Self::SIZE] {
132        self.0.to_le_bytes()
133    }
134
135    /// Segment index piece index corresponds to
136    #[inline]
137    pub const fn segment_index(&self) -> SegmentIndex {
138        SegmentIndex::new(self.0 / ArchivedHistorySegment::NUM_PIECES as u64)
139    }
140
141    /// Position of a piece in a segment
142    #[inline]
143    pub const fn position(&self) -> u32 {
144        // Position is statically guaranteed to fit into u32
145        (self.0 % ArchivedHistorySegment::NUM_PIECES as u64) as u32
146    }
147
148    /// Position of a source piece in the source pieces for a segment.
149    /// Panics if the piece is not a source piece.
150    #[inline]
151    pub const fn source_position(&self) -> u32 {
152        assert!(self.is_source());
153
154        let source_start = self.position() / RecordedHistorySegment::ERASURE_CODING_RATE.1 as u32
155            * RecordedHistorySegment::ERASURE_CODING_RATE.0 as u32;
156        let source_offset = self.position() % RecordedHistorySegment::ERASURE_CODING_RATE.1 as u32;
157
158        source_start + source_offset
159    }
160
161    /// Returns the piece index for a source position and segment index.
162    /// Overflows to the next segment if the position is greater than the last source position.
163    #[inline]
164    pub const fn from_source_position(
165        source_position: u32,
166        segment_index: SegmentIndex,
167    ) -> PieceIndex {
168        let source_position = source_position as u64;
169        let start = source_position / RecordedHistorySegment::ERASURE_CODING_RATE.0 as u64
170            * RecordedHistorySegment::ERASURE_CODING_RATE.1 as u64;
171        let offset = source_position % RecordedHistorySegment::ERASURE_CODING_RATE.0 as u64;
172
173        PieceIndex(segment_index.first_piece_index().0 + start + offset)
174    }
175
176    /// Is this piece index a source piece?
177    #[inline]
178    pub const fn is_source(&self) -> bool {
179        // Source pieces are interleaved with parity pieces, source first
180        self.0 % (RecordedHistorySegment::ERASURE_CODING_RATE.1 as u64)
181            < (RecordedHistorySegment::ERASURE_CODING_RATE.0 as u64)
182    }
183
184    /// Returns the next source piece index.
185    /// Panics if the piece is not a source piece.
186    #[inline]
187    pub const fn next_source_index(&self) -> PieceIndex {
188        PieceIndex::from_source_position(self.source_position() + 1, self.segment_index())
189    }
190
191    /// Returns the previous source piece index, if there is one.
192    /// Panics if the piece is not a source piece.
193    #[inline]
194    pub const fn prev_source_index(&self) -> Option<PieceIndex> {
195        if self.source_position() == 0 {
196            // TODO: when Option::map or ? become const, use them here
197            match self.segment_index().checked_sub(SegmentIndex::ONE) {
198                Some(segment_index) => Some(PieceIndex::from_source_position(
199                    RecordedHistorySegment::NUM_RAW_RECORDS as u32 - 1,
200                    segment_index,
201                )),
202                None => None,
203            }
204        } else {
205            Some(PieceIndex::from_source_position(
206                self.source_position() - 1,
207                self.segment_index(),
208            ))
209        }
210    }
211}
212
213/// Piece offset in sector
214#[derive(
215    Debug,
216    Display,
217    Default,
218    Copy,
219    Clone,
220    Ord,
221    PartialOrd,
222    Eq,
223    PartialEq,
224    Hash,
225    Encode,
226    Decode,
227    Add,
228    AddAssign,
229    Sub,
230    SubAssign,
231    Mul,
232    MulAssign,
233    Div,
234    DivAssign,
235    TypeInfo,
236    MaxEncodedLen,
237    DecodeWithMemTracking,
238)]
239#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
240#[repr(transparent)]
241pub struct PieceOffset(u16);
242
243impl Step for PieceOffset {
244    #[inline]
245    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
246        u16::steps_between(&start.0, &end.0)
247    }
248
249    #[inline]
250    fn forward_checked(start: Self, count: usize) -> Option<Self> {
251        u16::forward_checked(start.0, count).map(Self)
252    }
253
254    #[inline]
255    fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
256        let (n, overflowing) = u16::forward_overflowing(start.0, count);
257        (Self(n), overflowing)
258    }
259
260    #[inline]
261    fn backward_checked(start: Self, count: usize) -> Option<Self> {
262        u16::backward_checked(start.0, count).map(Self)
263    }
264
265    #[inline]
266    fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
267        let (n, overflowing) = u16::backward_overflowing(start.0, count);
268        (Self(n), overflowing)
269    }
270}
271
272impl From<u16> for PieceOffset {
273    #[inline]
274    fn from(original: u16) -> Self {
275        Self(original)
276    }
277}
278
279impl From<PieceOffset> for u16 {
280    #[inline]
281    fn from(original: PieceOffset) -> Self {
282        original.0
283    }
284}
285
286impl From<PieceOffset> for u32 {
287    #[inline]
288    fn from(original: PieceOffset) -> Self {
289        Self::from(original.0)
290    }
291}
292
293impl From<PieceOffset> for u64 {
294    #[inline]
295    fn from(original: PieceOffset) -> Self {
296        Self::from(original.0)
297    }
298}
299
300impl From<PieceOffset> for usize {
301    #[inline]
302    fn from(original: PieceOffset) -> Self {
303        usize::from(original.0)
304    }
305}
306
307impl PieceOffset {
308    /// Piece index 0.
309    pub const ZERO: PieceOffset = PieceOffset(0);
310    /// Piece index 1.
311    pub const ONE: PieceOffset = PieceOffset(1);
312
313    /// Convert piece offset to bytes.
314    #[inline]
315    pub const fn to_bytes(self) -> [u8; mem::size_of::<u16>()] {
316        self.0.to_le_bytes()
317    }
318}
319
320/// Raw record contained within recorded history segment before archiving is applied.
321///
322/// NOTE: This is a stack-allocated data structure and can cause stack overflow!
323#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
324#[repr(transparent)]
325pub struct RawRecord([[u8; ScalarBytes::SAFE_BYTES]; Self::NUM_CHUNKS]);
326
327impl fmt::Debug for RawRecord {
328    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
329        write!(f, "{}", hex::encode(self.0.as_flattened()))
330    }
331}
332
333impl Default for RawRecord {
334    #[inline]
335    fn default() -> Self {
336        Self([Default::default(); Self::NUM_CHUNKS])
337    }
338}
339
340impl AsRef<[u8]> for RawRecord {
341    #[inline]
342    fn as_ref(&self) -> &[u8] {
343        self.0.as_slice().as_flattened()
344    }
345}
346
347impl AsMut<[u8]> for RawRecord {
348    #[inline]
349    fn as_mut(&mut self) -> &mut [u8] {
350        self.0.as_mut_slice().as_flattened_mut()
351    }
352}
353
354impl From<&RawRecord> for &[[u8; ScalarBytes::SAFE_BYTES]; RawRecord::NUM_CHUNKS] {
355    #[inline]
356    fn from(value: &RawRecord) -> Self {
357        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
358        // layout
359        unsafe { mem::transmute(value) }
360    }
361}
362
363impl From<&[[u8; ScalarBytes::SAFE_BYTES]; RawRecord::NUM_CHUNKS]> for &RawRecord {
364    #[inline]
365    fn from(value: &[[u8; ScalarBytes::SAFE_BYTES]; RawRecord::NUM_CHUNKS]) -> Self {
366        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
367        // layout
368        unsafe { mem::transmute(value) }
369    }
370}
371
372impl From<&mut RawRecord> for &mut [[u8; ScalarBytes::SAFE_BYTES]; RawRecord::NUM_CHUNKS] {
373    #[inline]
374    fn from(value: &mut RawRecord) -> Self {
375        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
376        // layout
377        unsafe { mem::transmute(value) }
378    }
379}
380
381impl From<&mut [[u8; ScalarBytes::SAFE_BYTES]; RawRecord::NUM_CHUNKS]> for &mut RawRecord {
382    #[inline]
383    fn from(value: &mut [[u8; ScalarBytes::SAFE_BYTES]; RawRecord::NUM_CHUNKS]) -> Self {
384        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
385        // layout
386        unsafe { mem::transmute(value) }
387    }
388}
389
390impl From<&RawRecord> for &[u8; ScalarBytes::SAFE_BYTES * RawRecord::NUM_CHUNKS] {
391    #[inline]
392    fn from(value: &RawRecord) -> Self {
393        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
394        // layout as inner array, while array of byte arrays has the same alignment as a single byte
395        unsafe { mem::transmute(value) }
396    }
397}
398
399impl From<&[u8; ScalarBytes::SAFE_BYTES * RawRecord::NUM_CHUNKS]> for &RawRecord {
400    #[inline]
401    fn from(value: &[u8; ScalarBytes::SAFE_BYTES * RawRecord::NUM_CHUNKS]) -> Self {
402        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
403        // layout as inner array, while array of byte arrays has the same alignment as a single byte
404        unsafe { mem::transmute(value) }
405    }
406}
407
408impl From<&mut RawRecord> for &mut [u8; ScalarBytes::SAFE_BYTES * RawRecord::NUM_CHUNKS] {
409    #[inline]
410    fn from(value: &mut RawRecord) -> Self {
411        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
412        // layout as inner array, while array of byte arrays has the same alignment as a single byte
413        unsafe { mem::transmute(value) }
414    }
415}
416
417impl From<&mut [u8; ScalarBytes::SAFE_BYTES * RawRecord::NUM_CHUNKS]> for &mut RawRecord {
418    #[inline]
419    fn from(value: &mut [u8; ScalarBytes::SAFE_BYTES * RawRecord::NUM_CHUNKS]) -> Self {
420        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
421        // layout as inner array, while array of byte arrays has the same alignment as a single byte
422        unsafe { mem::transmute(value) }
423    }
424}
425
426impl RawRecord {
427    /// Number of chunks (scalars) within one raw record.
428    pub const NUM_CHUNKS: usize = 2_usize.pow(15);
429    /// Size of raw record in bytes, is guaranteed to be a multiple of [`ScalarBytes::SAFE_BYTES`].
430    pub const SIZE: usize = ScalarBytes::SAFE_BYTES * Self::NUM_CHUNKS;
431
432    /// Create boxed value without hitting stack overflow
433    #[inline]
434    pub fn new_boxed() -> Box<Self> {
435        // TODO: Should have been just `::new()`, but https://github.com/rust-lang/rust/issues/53827
436        // SAFETY: Data structure filled with zeroes is a valid invariant
437        unsafe { Box::new_zeroed().assume_init() }
438    }
439
440    /// Convenient conversion from slice of record to underlying representation for efficiency
441    /// purposes.
442    #[inline]
443    pub fn slice_to_repr(value: &[Self]) -> &[[[u8; ScalarBytes::SAFE_BYTES]; Self::NUM_CHUNKS]] {
444        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
445        // layout
446        unsafe { mem::transmute(value) }
447    }
448
449    /// Convenient conversion from slice of underlying representation to record for efficiency
450    /// purposes.
451    #[inline]
452    pub fn slice_from_repr(value: &[[[u8; ScalarBytes::SAFE_BYTES]; Self::NUM_CHUNKS]]) -> &[Self] {
453        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
454        // layout
455        unsafe { mem::transmute(value) }
456    }
457
458    /// Convenient conversion from mutable slice of record to underlying representation for
459    /// efficiency purposes.
460    #[inline]
461    pub fn slice_mut_to_repr(
462        value: &mut [Self],
463    ) -> &mut [[[u8; ScalarBytes::SAFE_BYTES]; Self::NUM_CHUNKS]] {
464        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
465        // layout
466        unsafe { mem::transmute(value) }
467    }
468
469    /// Convenient conversion from mutable slice of underlying representation to record for
470    /// efficiency purposes.
471    #[inline]
472    pub fn slice_mut_from_repr(
473        value: &mut [[[u8; ScalarBytes::SAFE_BYTES]; Self::NUM_CHUNKS]],
474    ) -> &mut [Self] {
475        // SAFETY: `RawRecord` is `#[repr(transparent)]` and guaranteed to have the same memory
476        // layout
477        unsafe { mem::transmute(value) }
478    }
479}
480
481/// Record contained within a piece.
482///
483/// NOTE: This is a stack-allocated data structure and can cause stack overflow!
484#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
485#[repr(transparent)]
486pub struct Record([[u8; ScalarBytes::FULL_BYTES]; Self::NUM_CHUNKS]);
487
488impl fmt::Debug for Record {
489    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
490        write!(f, "{}", hex::encode(self.0.as_flattened()))
491    }
492}
493
494impl Default for Record {
495    #[inline]
496    fn default() -> Self {
497        Self([Default::default(); Self::NUM_CHUNKS])
498    }
499}
500
501impl AsRef<[u8]> for Record {
502    #[inline]
503    fn as_ref(&self) -> &[u8] {
504        self.0.as_flattened()
505    }
506}
507
508impl AsMut<[u8]> for Record {
509    #[inline]
510    fn as_mut(&mut self) -> &mut [u8] {
511        self.0.as_flattened_mut()
512    }
513}
514
515impl From<&Record> for &[[u8; ScalarBytes::FULL_BYTES]; Record::NUM_CHUNKS] {
516    #[inline]
517    fn from(value: &Record) -> Self {
518        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
519        unsafe { mem::transmute(value) }
520    }
521}
522
523impl From<&[[u8; ScalarBytes::FULL_BYTES]; Record::NUM_CHUNKS]> for &Record {
524    #[inline]
525    fn from(value: &[[u8; ScalarBytes::FULL_BYTES]; Record::NUM_CHUNKS]) -> Self {
526        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
527        unsafe { mem::transmute(value) }
528    }
529}
530
531impl From<&mut Record> for &mut [[u8; ScalarBytes::FULL_BYTES]; Record::NUM_CHUNKS] {
532    #[inline]
533    fn from(value: &mut Record) -> Self {
534        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
535        unsafe { mem::transmute(value) }
536    }
537}
538
539impl From<&mut [[u8; ScalarBytes::FULL_BYTES]; Record::NUM_CHUNKS]> for &mut Record {
540    #[inline]
541    fn from(value: &mut [[u8; ScalarBytes::FULL_BYTES]; Record::NUM_CHUNKS]) -> Self {
542        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
543        unsafe { mem::transmute(value) }
544    }
545}
546
547impl From<&Record> for &[u8; ScalarBytes::FULL_BYTES * Record::NUM_CHUNKS] {
548    #[inline]
549    fn from(value: &Record) -> Self {
550        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
551        // as inner array, while array of byte arrays has the same alignment as a single byte
552        unsafe { mem::transmute(value) }
553    }
554}
555
556impl From<&[u8; ScalarBytes::FULL_BYTES * Record::NUM_CHUNKS]> for &Record {
557    #[inline]
558    fn from(value: &[u8; ScalarBytes::FULL_BYTES * Record::NUM_CHUNKS]) -> Self {
559        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
560        // as inner array, while array of byte arrays has the same alignment as a single byte
561        unsafe { mem::transmute(value) }
562    }
563}
564
565impl From<&mut Record> for &mut [u8; ScalarBytes::FULL_BYTES * Record::NUM_CHUNKS] {
566    #[inline]
567    fn from(value: &mut Record) -> Self {
568        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
569        // as inner array, while array of byte arrays has the same alignment as a single byte
570        unsafe { mem::transmute(value) }
571    }
572}
573
574impl From<&mut [u8; ScalarBytes::FULL_BYTES * Record::NUM_CHUNKS]> for &mut Record {
575    #[inline]
576    fn from(value: &mut [u8; ScalarBytes::FULL_BYTES * Record::NUM_CHUNKS]) -> Self {
577        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
578        // as inner array, while array of byte arrays has the same alignment as a single byte
579        unsafe { mem::transmute(value) }
580    }
581}
582
583impl Record {
584    /// Number of chunks (scalars) within one record.
585    pub const NUM_CHUNKS: usize = RawRecord::NUM_CHUNKS;
586    /// Number of s-buckets contained within one record (and by extension sector).
587    ///
588    /// Essentially we chunk records into scalars and erasure code them.
589    pub const NUM_S_BUCKETS: usize = Self::NUM_CHUNKS
590        * RecordedHistorySegment::ERASURE_CODING_RATE.1
591        / RecordedHistorySegment::ERASURE_CODING_RATE.0;
592    /// Size of a segment record given the global piece size (in bytes) after erasure coding
593    /// [`RawRecord`], is guaranteed to be a multiple of [`ScalarBytes::FULL_BYTES`].
594    pub const SIZE: usize = ScalarBytes::FULL_BYTES * Self::NUM_CHUNKS;
595
596    /// Create boxed value without hitting stack overflow
597    #[inline]
598    pub fn new_boxed() -> Box<Self> {
599        // TODO: Should have been just `::new()`, but https://github.com/rust-lang/rust/issues/53827
600        // SAFETY: Data structure filled with zeroes is a valid invariant
601        unsafe { Box::new_zeroed().assume_init() }
602    }
603
604    /// Create vector filled with zeroe records without hitting stack overflow
605    #[inline]
606    pub fn new_zero_vec(length: usize) -> Vec<Self> {
607        // TODO: Should have been just `::new()`, but https://github.com/rust-lang/rust/issues/53827
608        let mut records = Vec::with_capacity(length);
609        {
610            let slice = records.spare_capacity_mut();
611            // SAFETY: Same memory layout due to `#[repr(transparent)]` on `Record` and
612            // `MaybeUninit<[[T; M]; N]>` is guaranteed to have the same layout as
613            // `[[MaybeUninit<T>; M]; N]`
614            let slice = unsafe {
615                slice::from_raw_parts_mut(
616                    slice.as_mut_ptr()
617                        as *mut [[mem::MaybeUninit<u8>; ScalarBytes::FULL_BYTES]; Self::NUM_CHUNKS],
618                    length,
619                )
620            };
621            for byte in slice.as_flattened_mut().as_flattened_mut() {
622                byte.write(0);
623            }
624        }
625        // SAFETY: All values are initialized above.
626        unsafe {
627            records.set_len(records.capacity());
628        }
629
630        records
631    }
632
633    /// Convenient conversion from slice of record to underlying representation for efficiency
634    /// purposes.
635    #[inline]
636    pub fn slice_to_repr(value: &[Self]) -> &[[[u8; ScalarBytes::FULL_BYTES]; Self::NUM_CHUNKS]] {
637        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
638        unsafe { mem::transmute(value) }
639    }
640
641    /// Convenient conversion from slice of underlying representation to record for efficiency
642    /// purposes.
643    #[inline]
644    pub fn slice_from_repr(value: &[[[u8; ScalarBytes::FULL_BYTES]; Self::NUM_CHUNKS]]) -> &[Self] {
645        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
646        unsafe { mem::transmute(value) }
647    }
648
649    /// Convenient conversion from mutable slice of record to underlying representation for
650    /// efficiency purposes.
651    #[inline]
652    pub fn slice_mut_to_repr(
653        value: &mut [Self],
654    ) -> &mut [[[u8; ScalarBytes::FULL_BYTES]; Self::NUM_CHUNKS]] {
655        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
656        unsafe { mem::transmute(value) }
657    }
658
659    /// Convenient conversion from mutable slice of underlying representation to record for
660    /// efficiency purposes.
661    #[inline]
662    pub fn slice_mut_from_repr(
663        value: &mut [[[u8; ScalarBytes::FULL_BYTES]; Self::NUM_CHUNKS]],
664    ) -> &mut [Self] {
665        // SAFETY: `Record` is `#[repr(transparent)]` and guaranteed to have the same memory layout
666        unsafe { mem::transmute(value) }
667    }
668
669    /// Convert from a record to its raw bytes, assumes dealing with source record that only stores
670    /// safe bytes in its chunks.
671    #[inline]
672    pub fn to_raw_record_chunks(
673        &self,
674    ) -> impl DoubleEndedIterator<Item = &'_ [u8; ScalarBytes::SAFE_BYTES]> + '_ {
675        // We have zero byte padding from [`ScalarBytes::SAFE_BYTES`] to
676        // [`ScalarBytes::FULL_BYTES`] that we need to skip
677        self.iter()
678            .map(|bytes| bytes[1..].try_into().expect("Correct length; qed"))
679    }
680
681    /// Convert from a record to mutable raw bytes, assumes dealing with source record that only stores
682    /// safe bytes in its chunks.
683    #[inline]
684    pub fn to_mut_raw_record_chunks(
685        &mut self,
686    ) -> impl DoubleEndedIterator<Item = &'_ mut [u8; ScalarBytes::SAFE_BYTES]> + '_ {
687        self.iter_mut()
688            .map(|bytes| (&mut bytes[1..]).try_into().expect("Correct length; qed"))
689    }
690}
691
692/// Record commitment contained within a piece.
693#[derive(
694    Copy,
695    Clone,
696    Eq,
697    PartialEq,
698    Hash,
699    Deref,
700    DerefMut,
701    From,
702    Into,
703    Encode,
704    Decode,
705    TypeInfo,
706    MaxEncodedLen,
707    DecodeWithMemTracking,
708)]
709pub struct RecordCommitment([u8; RecordCommitment::SIZE]);
710
711impl fmt::Debug for RecordCommitment {
712    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
713        write!(f, "{}", hex::encode(self.0))
714    }
715}
716
717#[cfg(feature = "serde")]
718#[derive(Serialize, Deserialize)]
719#[serde(transparent)]
720struct RecordCommitmentBinary(#[serde(with = "BigArray")] [u8; RecordCommitment::SIZE]);
721
722#[cfg(feature = "serde")]
723#[derive(Serialize, Deserialize)]
724#[serde(transparent)]
725struct RecordCommitmentHex(#[serde(with = "hex")] [u8; RecordCommitment::SIZE]);
726
727#[cfg(feature = "serde")]
728impl Serialize for RecordCommitment {
729    #[inline]
730    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
731    where
732        S: Serializer,
733    {
734        if serializer.is_human_readable() {
735            RecordCommitmentHex(self.0).serialize(serializer)
736        } else {
737            RecordCommitmentBinary(self.0).serialize(serializer)
738        }
739    }
740}
741
742#[cfg(feature = "serde")]
743impl<'de> Deserialize<'de> for RecordCommitment {
744    #[inline]
745    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
746    where
747        D: Deserializer<'de>,
748    {
749        Ok(Self(if deserializer.is_human_readable() {
750            RecordCommitmentHex::deserialize(deserializer)?.0
751        } else {
752            RecordCommitmentBinary::deserialize(deserializer)?.0
753        }))
754    }
755}
756
757impl Default for RecordCommitment {
758    #[inline]
759    fn default() -> Self {
760        Self([0; Self::SIZE])
761    }
762}
763
764impl TryFrom<&[u8]> for RecordCommitment {
765    type Error = TryFromSliceError;
766
767    #[inline]
768    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
769        <[u8; Self::SIZE]>::try_from(slice).map(Self)
770    }
771}
772
773impl AsRef<[u8]> for RecordCommitment {
774    #[inline]
775    fn as_ref(&self) -> &[u8] {
776        &self.0
777    }
778}
779
780impl AsMut<[u8]> for RecordCommitment {
781    #[inline]
782    fn as_mut(&mut self) -> &mut [u8] {
783        &mut self.0
784    }
785}
786
787impl From<&RecordCommitment> for &[u8; RecordCommitment::SIZE] {
788    #[inline]
789    fn from(value: &RecordCommitment) -> Self {
790        // SAFETY: `RecordCommitment` is `#[repr(transparent)]` and guaranteed to have the same
791        // memory layout
792        unsafe { mem::transmute(value) }
793    }
794}
795
796impl From<&[u8; RecordCommitment::SIZE]> for &RecordCommitment {
797    #[inline]
798    fn from(value: &[u8; RecordCommitment::SIZE]) -> Self {
799        // SAFETY: `RecordCommitment` is `#[repr(transparent)]` and guaranteed to have the same
800        // memory layout
801        unsafe { mem::transmute(value) }
802    }
803}
804
805impl From<&mut RecordCommitment> for &mut [u8; RecordCommitment::SIZE] {
806    #[inline]
807    fn from(value: &mut RecordCommitment) -> Self {
808        // SAFETY: `RecordCommitment` is `#[repr(transparent)]` and guaranteed to have the same
809        // memory layout
810        unsafe { mem::transmute(value) }
811    }
812}
813
814impl From<&mut [u8; RecordCommitment::SIZE]> for &mut RecordCommitment {
815    #[inline]
816    fn from(value: &mut [u8; RecordCommitment::SIZE]) -> Self {
817        // SAFETY: `RecordCommitment` is `#[repr(transparent)]` and guaranteed to have the same
818        // memory layout
819        unsafe { mem::transmute(value) }
820    }
821}
822
823impl RecordCommitment {
824    /// Size of record commitment in bytes.
825    pub const SIZE: usize = 48;
826}
827
828/// Record witness contained within a piece.
829#[derive(
830    Copy,
831    Clone,
832    Eq,
833    PartialEq,
834    Hash,
835    Deref,
836    DerefMut,
837    From,
838    Into,
839    Encode,
840    Decode,
841    TypeInfo,
842    MaxEncodedLen,
843    DecodeWithMemTracking,
844)]
845pub struct RecordWitness([u8; RecordWitness::SIZE]);
846
847impl fmt::Debug for RecordWitness {
848    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
849        write!(f, "{}", hex::encode(self.0))
850    }
851}
852
853#[cfg(feature = "serde")]
854#[derive(Serialize, Deserialize)]
855#[serde(transparent)]
856struct RecordWitnessBinary(#[serde(with = "BigArray")] [u8; RecordWitness::SIZE]);
857
858#[cfg(feature = "serde")]
859#[derive(Serialize, Deserialize)]
860#[serde(transparent)]
861struct RecordWitnessHex(#[serde(with = "hex")] [u8; RecordWitness::SIZE]);
862
863#[cfg(feature = "serde")]
864impl Serialize for RecordWitness {
865    #[inline]
866    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
867    where
868        S: Serializer,
869    {
870        if serializer.is_human_readable() {
871            RecordWitnessHex(self.0).serialize(serializer)
872        } else {
873            RecordWitnessBinary(self.0).serialize(serializer)
874        }
875    }
876}
877
878#[cfg(feature = "serde")]
879impl<'de> Deserialize<'de> for RecordWitness {
880    #[inline]
881    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
882    where
883        D: Deserializer<'de>,
884    {
885        Ok(Self(if deserializer.is_human_readable() {
886            RecordWitnessHex::deserialize(deserializer)?.0
887        } else {
888            RecordWitnessBinary::deserialize(deserializer)?.0
889        }))
890    }
891}
892
893impl Default for RecordWitness {
894    #[inline]
895    fn default() -> Self {
896        Self([0; Self::SIZE])
897    }
898}
899
900impl TryFrom<&[u8]> for RecordWitness {
901    type Error = TryFromSliceError;
902
903    #[inline]
904    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
905        <[u8; Self::SIZE]>::try_from(slice).map(Self)
906    }
907}
908
909impl AsRef<[u8]> for RecordWitness {
910    #[inline]
911    fn as_ref(&self) -> &[u8] {
912        &self.0
913    }
914}
915
916impl AsMut<[u8]> for RecordWitness {
917    #[inline]
918    fn as_mut(&mut self) -> &mut [u8] {
919        &mut self.0
920    }
921}
922
923impl From<&RecordWitness> for &[u8; RecordWitness::SIZE] {
924    #[inline]
925    fn from(value: &RecordWitness) -> Self {
926        // SAFETY: `RecordWitness` is `#[repr(transparent)]` and guaranteed to have the same
927        // memory layout
928        unsafe { mem::transmute(value) }
929    }
930}
931
932impl From<&[u8; RecordWitness::SIZE]> for &RecordWitness {
933    #[inline]
934    fn from(value: &[u8; RecordWitness::SIZE]) -> Self {
935        // SAFETY: `RecordWitness` is `#[repr(transparent)]` and guaranteed to have the same
936        // memory layout
937        unsafe { mem::transmute(value) }
938    }
939}
940
941impl From<&mut RecordWitness> for &mut [u8; RecordWitness::SIZE] {
942    #[inline]
943    fn from(value: &mut RecordWitness) -> Self {
944        // SAFETY: `RecordWitness` is `#[repr(transparent)]` and guaranteed to have the same
945        // memory layout
946        unsafe { mem::transmute(value) }
947    }
948}
949
950impl From<&mut [u8; RecordWitness::SIZE]> for &mut RecordWitness {
951    #[inline]
952    fn from(value: &mut [u8; RecordWitness::SIZE]) -> Self {
953        // SAFETY: `RecordWitness` is `#[repr(transparent)]` and guaranteed to have the same
954        // memory layout
955        unsafe { mem::transmute(value) }
956    }
957}
958
959impl RecordWitness {
960    /// Size of record witness in bytes.
961    pub const SIZE: usize = 48;
962}
963
964enum CowBytes {
965    Shared(Bytes),
966    Owned(BytesMut),
967}
968
969impl fmt::Debug for CowBytes {
970    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
971        write!(f, "{}", hex::encode(self.as_ref()))
972    }
973}
974
975impl PartialEq for CowBytes {
976    fn eq(&self, other: &Self) -> bool {
977        self.as_ref().eq(other.as_ref())
978    }
979}
980
981impl Eq for CowBytes {}
982
983impl Hash for CowBytes {
984    fn hash<H: Hasher>(&self, state: &mut H) {
985        self.as_ref().hash(state)
986    }
987}
988
989impl Clone for CowBytes {
990    fn clone(&self) -> Self {
991        match self {
992            Self::Shared(bytes) => Self::Shared(bytes.clone()),
993            // Always return shared clone
994            Self::Owned(bytes) => Self::Shared(Bytes::copy_from_slice(bytes)),
995        }
996    }
997}
998
999impl AsRef<[u8]> for CowBytes {
1000    fn as_ref(&self) -> &[u8] {
1001        match self {
1002            CowBytes::Shared(bytes) => bytes.as_ref(),
1003            CowBytes::Owned(bytes) => bytes.as_ref(),
1004        }
1005    }
1006}
1007
1008impl AsMut<[u8]> for CowBytes {
1009    #[inline]
1010    fn as_mut(&mut self) -> &mut [u8] {
1011        match self {
1012            CowBytes::Shared(bytes) => {
1013                *self = CowBytes::Owned(BytesMut::from(mem::take(bytes)));
1014
1015                let CowBytes::Owned(bytes) = self else {
1016                    unreachable!("Just replaced; qed");
1017                };
1018
1019                bytes.as_mut()
1020            }
1021            CowBytes::Owned(bytes) => bytes.as_mut(),
1022        }
1023    }
1024}
1025
1026/// A piece of archival history in Subspace Network.
1027///
1028/// This version is allocated on the heap, for stack-allocated piece see [`PieceArray`].
1029///
1030/// Internally piece contains a record and corresponding witness that together with segment
1031/// commitment of the segment this piece belongs to can be used to verify that a piece belongs to
1032/// the actual archival history of the blockchain.
1033#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1034pub struct Piece(CowBytes);
1035
1036impl Encode for Piece {
1037    #[inline]
1038    fn size_hint(&self) -> usize {
1039        self.as_ref().size_hint()
1040    }
1041
1042    #[inline]
1043    fn encode_to<O: Output + ?Sized>(&self, output: &mut O) {
1044        self.as_ref().encode_to(output)
1045    }
1046
1047    #[inline]
1048    fn encode(&self) -> Vec<u8> {
1049        self.as_ref().encode()
1050    }
1051
1052    #[inline]
1053    fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
1054        self.as_ref().using_encoded(f)
1055    }
1056}
1057
1058impl EncodeLike for Piece {}
1059
1060impl Decode for Piece {
1061    fn decode<I: Input>(input: &mut I) -> Result<Self, parity_scale_codec::Error> {
1062        let bytes =
1063            Bytes::decode(input).map_err(|error| error.chain("Could not decode `Piece`"))?;
1064
1065        if bytes.len() != Self::SIZE {
1066            return Err(
1067                parity_scale_codec::Error::from("Incorrect Piece length").chain(format!(
1068                    "Expected {} bytes, found {} bytes",
1069                    Self::SIZE,
1070                    bytes.len()
1071                )),
1072            );
1073        }
1074
1075        Ok(Piece(CowBytes::Shared(bytes)))
1076    }
1077}
1078
1079impl TypeInfo for Piece {
1080    type Identity = Self;
1081
1082    fn type_info() -> Type {
1083        Type::builder()
1084            .path(Path::new("Piece", module_path!()))
1085            .docs(&["A piece of archival history in Subspace Network"])
1086            .composite(
1087                Fields::unnamed().field(|f| f.ty::<[u8; Piece::SIZE]>().type_name("PieceArray")),
1088            )
1089    }
1090}
1091
1092#[cfg(feature = "serde")]
1093impl Serialize for Piece {
1094    #[inline]
1095    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1096    where
1097        S: Serializer,
1098    {
1099        let bytes = match &self.0 {
1100            CowBytes::Shared(bytes) => bytes.as_ref(),
1101            CowBytes::Owned(bytes) => bytes.as_ref(),
1102        };
1103
1104        if serializer.is_human_readable() {
1105            hex::serde::serialize(bytes, serializer)
1106        } else {
1107            bytes.serialize(serializer)
1108        }
1109    }
1110}
1111
1112#[cfg(feature = "serde")]
1113impl<'de> Deserialize<'de> for Piece {
1114    #[inline]
1115    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1116    where
1117        D: Deserializer<'de>,
1118    {
1119        let bytes = if deserializer.is_human_readable() {
1120            hex::serde::deserialize::<_, Vec<u8>>(deserializer).and_then(|bytes| {
1121                if bytes.len() == Piece::SIZE {
1122                    Ok(Bytes::from(bytes))
1123                } else {
1124                    Err(serde::de::Error::invalid_length(
1125                        bytes.len(),
1126                        &format!("Expected {} bytes", Piece::SIZE).as_str(),
1127                    ))
1128                }
1129            })?
1130        } else {
1131            Bytes::deserialize(deserializer)?
1132        };
1133
1134        Ok(Piece(CowBytes::Shared(bytes)))
1135    }
1136}
1137
1138impl Default for Piece {
1139    #[inline]
1140    fn default() -> Self {
1141        Self(CowBytes::Owned(BytesMut::zeroed(Self::SIZE)))
1142    }
1143}
1144
1145impl From<Piece> for Vec<u8> {
1146    #[inline]
1147    fn from(piece: Piece) -> Self {
1148        match piece.0 {
1149            CowBytes::Shared(bytes) => bytes.to_vec(),
1150            CowBytes::Owned(bytes) => Vec::from(bytes),
1151        }
1152    }
1153}
1154
1155impl TryFrom<&[u8]> for Piece {
1156    type Error = ();
1157
1158    #[inline]
1159    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
1160        if slice.len() != Self::SIZE {
1161            return Err(());
1162        }
1163
1164        Ok(Self(CowBytes::Shared(Bytes::copy_from_slice(slice))))
1165    }
1166}
1167
1168impl TryFrom<Vec<u8>> for Piece {
1169    type Error = ();
1170
1171    #[inline]
1172    fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
1173        if vec.len() != Self::SIZE {
1174            return Err(());
1175        }
1176
1177        Ok(Self(CowBytes::Shared(Bytes::from(vec))))
1178    }
1179}
1180
1181impl TryFrom<Bytes> for Piece {
1182    type Error = ();
1183
1184    #[inline]
1185    fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
1186        if bytes.len() != Self::SIZE {
1187            return Err(());
1188        }
1189
1190        Ok(Self(CowBytes::Shared(bytes)))
1191    }
1192}
1193
1194impl TryFrom<BytesMut> for Piece {
1195    type Error = ();
1196
1197    #[inline]
1198    fn try_from(bytes: BytesMut) -> Result<Self, Self::Error> {
1199        if bytes.len() != Self::SIZE {
1200            return Err(());
1201        }
1202
1203        Ok(Self(CowBytes::Owned(bytes)))
1204    }
1205}
1206
1207impl From<&PieceArray> for Piece {
1208    #[inline]
1209    fn from(value: &PieceArray) -> Self {
1210        Self(CowBytes::Shared(Bytes::copy_from_slice(value.as_ref())))
1211    }
1212}
1213
1214impl Deref for Piece {
1215    type Target = PieceArray;
1216
1217    #[inline]
1218    fn deref(&self) -> &Self::Target {
1219        <&[u8; Self::SIZE]>::try_from(self.as_ref())
1220            .expect("Slice of memory has correct length; qed")
1221            .into()
1222    }
1223}
1224
1225impl DerefMut for Piece {
1226    #[inline]
1227    fn deref_mut(&mut self) -> &mut Self::Target {
1228        <&mut [u8; Self::SIZE]>::try_from(self.as_mut())
1229            .expect("Slice of memory has correct length; qed")
1230            .into()
1231    }
1232}
1233
1234impl AsRef<[u8]> for Piece {
1235    #[inline]
1236    fn as_ref(&self) -> &[u8] {
1237        self.0.as_ref()
1238    }
1239}
1240
1241impl AsMut<[u8]> for Piece {
1242    #[inline]
1243    fn as_mut(&mut self) -> &mut [u8] {
1244        self.0.as_mut()
1245    }
1246}
1247
1248impl Piece {
1249    /// Size of a piece (in bytes).
1250    pub const SIZE: usize = Record::SIZE + RecordCommitment::SIZE + RecordWitness::SIZE;
1251
1252    /// Ensure piece contains cheaply cloneable shared data.
1253    ///
1254    /// Internally piece uses CoW mechanism and can store either mutable owned data or data that is
1255    /// cheap to clone, calling this method will ensure further clones will not result in additional
1256    /// memory allocations.
1257    pub fn to_shared(self) -> Self {
1258        Self(match self.0 {
1259            CowBytes::Shared(bytes) => CowBytes::Shared(bytes),
1260            CowBytes::Owned(bytes) => CowBytes::Shared(bytes.freeze()),
1261        })
1262    }
1263}
1264
1265/// A piece of archival history in Subspace Network.
1266///
1267/// This version is allocated on the stack, for heap-allocated piece see [`Piece`].
1268///
1269/// Internally piece contains a record and corresponding witness that together with segment
1270/// commitment of the segment this piece belongs to can be used to verify that a piece belongs to
1271/// the actual archival history of the blockchain.
1272#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deref, DerefMut, AsRef, AsMut)]
1273#[repr(transparent)]
1274pub struct PieceArray([u8; Piece::SIZE]);
1275
1276impl fmt::Debug for PieceArray {
1277    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1278        write!(f, "{}", hex::encode(self.0))
1279    }
1280}
1281
1282impl Default for PieceArray {
1283    #[inline]
1284    fn default() -> Self {
1285        Self([0u8; Piece::SIZE])
1286    }
1287}
1288
1289impl AsRef<[u8]> for PieceArray {
1290    #[inline]
1291    fn as_ref(&self) -> &[u8] {
1292        &self.0
1293    }
1294}
1295
1296impl AsMut<[u8]> for PieceArray {
1297    #[inline]
1298    fn as_mut(&mut self) -> &mut [u8] {
1299        &mut self.0
1300    }
1301}
1302
1303impl From<&PieceArray> for &[u8; Piece::SIZE] {
1304    #[inline]
1305    fn from(value: &PieceArray) -> Self {
1306        // SAFETY: `PieceArray` is `#[repr(transparent)]` and guaranteed to have the same memory
1307        // layout
1308        unsafe { mem::transmute(value) }
1309    }
1310}
1311
1312impl From<&[u8; Piece::SIZE]> for &PieceArray {
1313    #[inline]
1314    fn from(value: &[u8; Piece::SIZE]) -> Self {
1315        // SAFETY: `PieceArray` is `#[repr(transparent)]` and guaranteed to have the same memory
1316        // layout
1317        unsafe { mem::transmute(value) }
1318    }
1319}
1320
1321impl From<&mut PieceArray> for &mut [u8; Piece::SIZE] {
1322    #[inline]
1323    fn from(value: &mut PieceArray) -> Self {
1324        // SAFETY: `PieceArray` is `#[repr(transparent)]` and guaranteed to have the same memory
1325        // layout
1326        unsafe { mem::transmute(value) }
1327    }
1328}
1329
1330impl From<&mut [u8; Piece::SIZE]> for &mut PieceArray {
1331    #[inline]
1332    fn from(value: &mut [u8; Piece::SIZE]) -> Self {
1333        // SAFETY: `PieceArray` is `#[repr(transparent)]` and guaranteed to have the same memory
1334        // layout
1335        unsafe { mem::transmute(value) }
1336    }
1337}
1338
1339impl PieceArray {
1340    /// Create boxed value without hitting stack overflow
1341    #[inline]
1342    pub fn new_boxed() -> Box<Self> {
1343        // TODO: Should have been just `::new()`, but https://github.com/rust-lang/rust/issues/53827
1344        // SAFETY: Data structure filled with zeroes is a valid invariant
1345        unsafe { Box::<Self>::new_zeroed().assume_init() }
1346    }
1347
1348    /// Split piece into underlying components.
1349    #[inline]
1350    pub fn split(&self) -> (&Record, &RecordCommitment, &RecordWitness) {
1351        let (record, extra) = self.0.split_at(Record::SIZE);
1352        let (commitment, witness) = extra.split_at(RecordCommitment::SIZE);
1353
1354        let record = <&[u8; Record::SIZE]>::try_from(record)
1355            .expect("Slice of memory has correct length; qed");
1356        let commitment = <&[u8; RecordCommitment::SIZE]>::try_from(commitment)
1357            .expect("Slice of memory has correct length; qed");
1358        let witness = <&[u8; RecordWitness::SIZE]>::try_from(witness)
1359            .expect("Slice of memory has correct length; qed");
1360
1361        (record.into(), commitment.into(), witness.into())
1362    }
1363
1364    /// Split piece into underlying mutable components.
1365    #[inline]
1366    pub fn split_mut(&mut self) -> (&mut Record, &mut RecordCommitment, &mut RecordWitness) {
1367        let (record, extra) = self.0.split_at_mut(Record::SIZE);
1368        let (commitment, witness) = extra.split_at_mut(RecordCommitment::SIZE);
1369
1370        let record = <&mut [u8; Record::SIZE]>::try_from(record)
1371            .expect("Slice of memory has correct length; qed");
1372        let commitment = <&mut [u8; RecordCommitment::SIZE]>::try_from(commitment)
1373            .expect("Slice of memory has correct length; qed");
1374        let witness = <&mut [u8; RecordWitness::SIZE]>::try_from(witness)
1375            .expect("Slice of memory has correct length; qed");
1376
1377        (record.into(), commitment.into(), witness.into())
1378    }
1379
1380    /// Record contained within a piece.
1381    #[inline]
1382    pub fn record(&self) -> &Record {
1383        self.split().0
1384    }
1385
1386    /// Mutable record contained within a piece.
1387    #[inline]
1388    pub fn record_mut(&mut self) -> &mut Record {
1389        self.split_mut().0
1390    }
1391
1392    /// Commitment contained within a piece.
1393    #[inline]
1394    pub fn commitment(&self) -> &RecordCommitment {
1395        self.split().1
1396    }
1397
1398    /// Mutable commitment contained within a piece.
1399    #[inline]
1400    pub fn commitment_mut(&mut self) -> &mut RecordCommitment {
1401        self.split_mut().1
1402    }
1403
1404    /// Witness contained within a piece.
1405    #[inline]
1406    pub fn witness(&self) -> &RecordWitness {
1407        self.split().2
1408    }
1409
1410    /// Mutable witness contained within a piece.
1411    #[inline]
1412    pub fn witness_mut(&mut self) -> &mut RecordWitness {
1413        self.split_mut().2
1414    }
1415
1416    /// Convenient conversion from slice of piece array to underlying representation for efficiency
1417    /// purposes.
1418    #[inline]
1419    pub fn slice_to_repr(value: &[Self]) -> &[[u8; Piece::SIZE]] {
1420        // SAFETY: `PieceArray` is `#[repr(transparent)]` and guaranteed to have the same memory
1421        // layout
1422        unsafe { mem::transmute(value) }
1423    }
1424
1425    /// Convenient conversion from slice of underlying representation to piece array for efficiency
1426    /// purposes.
1427    #[inline]
1428    pub fn slice_from_repr(value: &[[u8; Piece::SIZE]]) -> &[Self] {
1429        // SAFETY: `PieceArray` is `#[repr(transparent)]` and guaranteed to have the same memory
1430        // layout
1431        unsafe { mem::transmute(value) }
1432    }
1433
1434    /// Convenient conversion from mutable slice of piece array to underlying representation for
1435    /// efficiency purposes.
1436    #[inline]
1437    pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; Piece::SIZE]] {
1438        // SAFETY: `PieceArray` is `#[repr(transparent)]` and guaranteed to have the same memory
1439        // layout
1440        unsafe { mem::transmute(value) }
1441    }
1442
1443    /// Convenient conversion from mutable slice of underlying representation to piece array for
1444    /// efficiency purposes.
1445    #[inline]
1446    pub fn slice_mut_from_repr(value: &mut [[u8; Piece::SIZE]]) -> &mut [Self] {
1447        // SAFETY: `PieceArray` is `#[repr(transparent)]` and guaranteed to have the same memory
1448        // layout
1449        unsafe { mem::transmute(value) }
1450    }
1451}
1452
1453impl From<Box<PieceArray>> for Vec<u8> {
1454    fn from(value: Box<PieceArray>) -> Self {
1455        let mut value = mem::ManuallyDrop::new(value);
1456        // SAFETY: Always contains fixed allocation of bytes
1457        unsafe { Vec::from_raw_parts(value.as_mut_ptr(), Piece::SIZE, Piece::SIZE) }
1458    }
1459}
1460
1461/// Flat representation of multiple pieces concatenated for more efficient for processing
1462#[derive(Clone, PartialEq, Eq)]
1463pub struct FlatPieces(CowBytes);
1464
1465impl fmt::Debug for FlatPieces {
1466    #[inline]
1467    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1468        f.debug_struct("FlatPieces").finish_non_exhaustive()
1469    }
1470}
1471
1472impl Deref for FlatPieces {
1473    type Target = [PieceArray];
1474
1475    #[inline]
1476    fn deref(&self) -> &Self::Target {
1477        let bytes = self.0.as_ref();
1478        // SAFETY: Bytes slice has length of multiples of piece size and lifetimes of returned data
1479        // are preserved
1480        let pieces = unsafe {
1481            slice::from_raw_parts(
1482                bytes.as_ptr() as *const [u8; Piece::SIZE],
1483                bytes.len() / Piece::SIZE,
1484            )
1485        };
1486        PieceArray::slice_from_repr(pieces)
1487    }
1488}
1489
1490impl DerefMut for FlatPieces {
1491    #[inline]
1492    fn deref_mut(&mut self) -> &mut Self::Target {
1493        let bytes = self.0.as_mut();
1494        // SAFETY: Bytes slice has length of multiples of piece size and lifetimes of returned data
1495        // are preserved
1496        let pieces = unsafe {
1497            slice::from_raw_parts_mut(
1498                bytes.as_mut_ptr() as *mut [u8; Piece::SIZE],
1499                bytes.len() / Piece::SIZE,
1500            )
1501        };
1502        PieceArray::slice_mut_from_repr(pieces)
1503    }
1504}
1505
1506impl FlatPieces {
1507    /// Allocate `FlatPieces` that will hold `piece_count` pieces filled with zeroes
1508    #[inline]
1509    pub fn new(piece_count: usize) -> Self {
1510        Self(CowBytes::Owned(BytesMut::zeroed(piece_count * Piece::SIZE)))
1511    }
1512
1513    /// Iterate over all pieces.
1514    ///
1515    /// NOTE: Unless [`Self::to_shared`] was called first, iterator may have to allocate each piece
1516    /// from scratch, which is rarely a desired behavior.
1517    #[inline]
1518    pub fn pieces(&self) -> Box<dyn ExactSizeIterator<Item = Piece> + '_> {
1519        match &self.0 {
1520            CowBytes::Shared(bytes) => Box::new(
1521                bytes
1522                    .as_chunks::<{ Piece::SIZE }>()
1523                    .0
1524                    .iter()
1525                    .map(|slice| Piece(CowBytes::Shared(bytes.slice_ref(slice)))),
1526            ),
1527            CowBytes::Owned(bytes) => Box::new(
1528                bytes
1529                    .as_chunks::<{ Piece::SIZE }>()
1530                    .0
1531                    .iter()
1532                    .map(|slice| Piece(CowBytes::Shared(Bytes::copy_from_slice(slice)))),
1533            ),
1534        }
1535    }
1536
1537    /// Iterator over source pieces (even indices)
1538    #[inline]
1539    pub fn source_pieces(&self) -> impl ExactSizeIterator<Item = Piece> + '_ {
1540        self.pieces().step_by(2)
1541    }
1542
1543    /// Iterator over source pieces (even indices)
1544    #[inline]
1545    pub fn source(&self) -> impl ExactSizeIterator<Item = &'_ PieceArray> + '_ {
1546        self.iter().step_by(2)
1547    }
1548
1549    /// Mutable iterator over source pieces (even indices)
1550    #[inline]
1551    pub fn source_mut(&mut self) -> impl ExactSizeIterator<Item = &'_ mut PieceArray> + '_ {
1552        self.iter_mut().step_by(2)
1553    }
1554
1555    /// Iterator over parity pieces (odd indices)
1556    #[inline]
1557    pub fn parity_pieces(&self) -> impl ExactSizeIterator<Item = Piece> + '_ {
1558        self.pieces().skip(1).step_by(2)
1559    }
1560
1561    /// Iterator over parity pieces (odd indices)
1562    #[inline]
1563    pub fn parity(&self) -> impl ExactSizeIterator<Item = &'_ PieceArray> + '_ {
1564        self.iter().skip(1).step_by(2)
1565    }
1566
1567    /// Mutable iterator over parity pieces (odd indices)
1568    #[inline]
1569    pub fn parity_mut(&mut self) -> impl ExactSizeIterator<Item = &'_ mut PieceArray> + '_ {
1570        self.iter_mut().skip(1).step_by(2)
1571    }
1572
1573    /// Ensure flat pieces contains cheaply cloneable shared data.
1574    ///
1575    /// Internally flat pieces uses CoW mechanism and can store either mutable owned data or data
1576    /// that is cheap to clone, calling this method will ensure further clones and returned pieces
1577    /// will not result in additional memory allocations.
1578    pub fn to_shared(self) -> Self {
1579        Self(match self.0 {
1580            CowBytes::Shared(bytes) => CowBytes::Shared(bytes),
1581            CowBytes::Owned(bytes) => CowBytes::Shared(bytes.freeze()),
1582        })
1583    }
1584}
1585
1586#[cfg(feature = "parallel")]
1587impl FlatPieces {
1588    /// Parallel iterator over source pieces (even indices)
1589    #[inline]
1590    pub fn par_source(&self) -> impl IndexedParallelIterator<Item = &'_ PieceArray> + '_ {
1591        self.par_iter().step_by(2)
1592    }
1593
1594    /// Mutable parallel iterator over source pieces (even indices)
1595    #[inline]
1596    pub fn par_source_mut(
1597        &mut self,
1598    ) -> impl IndexedParallelIterator<Item = &'_ mut PieceArray> + '_ {
1599        self.par_iter_mut().step_by(2)
1600    }
1601
1602    /// Parallel iterator over parity pieces (odd indices)
1603    #[inline]
1604    pub fn par_parity(&self) -> impl IndexedParallelIterator<Item = &'_ PieceArray> + '_ {
1605        self.par_iter().skip(1).step_by(2)
1606    }
1607
1608    /// Mutable parallel iterator over parity pieces (odd indices)
1609    #[inline]
1610    pub fn par_parity_mut(
1611        &mut self,
1612    ) -> impl IndexedParallelIterator<Item = &'_ mut PieceArray> + '_ {
1613        self.par_iter_mut().skip(1).step_by(2)
1614    }
1615}