Skip to main content

ab_core_primitives/segments/
archival_history_segment.rs

1use crate::pieces::{FlatPieces, InnerPiece, Piece, PiecePosition, Record};
2use crate::segments::RecordedHistorySegment;
3use derive_more::{Deref, DerefMut};
4use std::ops::{Index, IndexMut};
5use std::{array, mem};
6
7/// Archived history segment after archiving is applied.
8#[derive(Debug, Clone, Eq, PartialEq, Deref, DerefMut)]
9#[repr(transparent)]
10pub struct ArchivedHistorySegment(FlatPieces);
11
12impl AsRef<[InnerPiece; Self::NUM_PIECES]> for ArchivedHistorySegment {
13    #[inline(always)]
14    fn as_ref(&self) -> &[InnerPiece; Self::NUM_PIECES] {
15        self.0
16            .as_ref()
17            .try_into()
18            .expect("Constructor always produces correct length; qed")
19    }
20}
21
22impl AsMut<[InnerPiece; Self::NUM_PIECES]> for ArchivedHistorySegment {
23    #[inline(always)]
24    fn as_mut(&mut self) -> &mut [InnerPiece; Self::NUM_PIECES] {
25        self.0
26            .as_mut()
27            .try_into()
28            .expect("Constructor always produces correct length; qed")
29    }
30}
31
32impl AsRef<[[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2]> for ArchivedHistorySegment {
33    #[inline(always)]
34    fn as_ref(&self) -> &[[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2] {
35        const {
36            assert!(
37                RecordedHistorySegment::NUM_PIECES == RecordedHistorySegment::NUM_RAW_RECORDS * 2
38            );
39        }
40        // SAFETY: The same size and layout
41        unsafe {
42            mem::transmute::<
43                &[InnerPiece; Self::NUM_PIECES],
44                &[[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2],
45            >(self.as_ref())
46        }
47    }
48}
49
50impl AsMut<[[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2]> for ArchivedHistorySegment {
51    #[inline(always)]
52    fn as_mut(&mut self) -> &mut [[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2] {
53        const {
54            assert!(
55                RecordedHistorySegment::NUM_PIECES == RecordedHistorySegment::NUM_RAW_RECORDS * 2
56            );
57        }
58        // SAFETY: The same size and layout
59        unsafe {
60            mem::transmute::<
61                &mut [InnerPiece; Self::NUM_PIECES],
62                &mut [[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2],
63            >(self.as_mut())
64        }
65    }
66}
67
68impl Default for ArchivedHistorySegment {
69    #[inline]
70    fn default() -> Self {
71        Self(FlatPieces::new(Self::NUM_PIECES))
72    }
73}
74
75impl Index<PiecePosition> for ArchivedHistorySegment {
76    type Output = InnerPiece;
77
78    fn index(&self, index: PiecePosition) -> &Self::Output {
79        // SAFETY: The size of the archived history segment is known and protected invariant
80        unsafe { self.get_unchecked(usize::from(index)) }
81    }
82}
83
84impl IndexMut<PiecePosition> for ArchivedHistorySegment {
85    fn index_mut(&mut self, index: PiecePosition) -> &mut Self::Output {
86        // SAFETY: The size of the archived history segment is known and protected invariant
87        unsafe { self.get_unchecked_mut(usize::from(index)) }
88    }
89}
90
91impl ArchivedHistorySegment {
92    /// All records of this segment, split into source and parity halves
93    #[inline(always)]
94    pub fn split_records_mut(
95        &mut self,
96    ) -> (
97        [&mut Record; RecordedHistorySegment::NUM_RAW_RECORDS],
98        [&mut Record; RecordedHistorySegment::NUM_RAW_RECORDS],
99    ) {
100        let [source, parity]: &mut [[_; RecordedHistorySegment::NUM_RAW_RECORDS]; 2] =
101            self.as_mut();
102        let mut source = source.iter_mut().map(|piece| &mut piece.record);
103        let mut parity = parity.iter_mut().map(|piece| &mut piece.record);
104
105        (
106            array::from_fn(|_| {
107                source
108                    .next()
109                    .expect("Number of pieces matches the array size; qed")
110            }),
111            array::from_fn(|_| {
112                parity
113                    .next()
114                    .expect("Number of pieces matches the array size; qed")
115            }),
116        )
117    }
118
119    /// Number of pieces in one segment of archived history.
120    pub const NUM_PIECES: usize = RecordedHistorySegment::NUM_PIECES;
121    /// Size of archived history segment in bytes.
122    ///
123    /// It includes erasure coded [`InnerPiece`]s (both source and parity) that are
124    /// composed of [`crate::pieces::Record`]s together with corresponding roots and
125    /// proofs.
126    pub const SIZE: usize = Piece::SIZE * Self::NUM_PIECES;
127
128    /// Ensure archived history segment contains cheaply cloneable shared data.
129    ///
130    /// Internally archived history segment uses CoW mechanism and can store either mutable owned
131    /// data or data that is cheap to clone, calling this method will ensure further clones and
132    /// returned pieces will not result in additional memory allocations.
133    pub fn to_shared(self) -> Self {
134        Self(self.0.to_shared())
135    }
136}