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 alloc::boxed::Box;
4use array_reshape::Unflatten;
5use std::array;
6use std::ops::{Deref, DerefMut, Index, IndexMut};
7
8/// Archived history segment after archiving is applied.
9///
10/// Dereferences to a fixed-size array of pieces, such that the number of pieces can't be changed.
11#[derive(Debug, Clone, Eq, PartialEq)]
12#[repr(transparent)]
13pub struct ArchivedHistorySegment(FlatPieces);
14
15impl AsRef<[InnerPiece; Self::NUM_PIECES]> for ArchivedHistorySegment {
16    #[inline(always)]
17    fn as_ref(&self) -> &[InnerPiece; Self::NUM_PIECES] {
18        self.0
19            .as_ref()
20            .try_into()
21            .expect("Constructor always produces correct length; qed")
22    }
23}
24
25impl AsMut<[InnerPiece; Self::NUM_PIECES]> for ArchivedHistorySegment {
26    #[inline(always)]
27    fn as_mut(&mut self) -> &mut [InnerPiece; Self::NUM_PIECES] {
28        self.0
29            .as_mut()
30            .try_into()
31            .expect("Constructor always produces correct length; qed")
32    }
33}
34
35impl AsRef<[[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2]> for ArchivedHistorySegment {
36    #[inline(always)]
37    fn as_ref(&self) -> &[[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2] {
38        let pieces: &[InnerPiece; Self::NUM_PIECES] = self.as_ref();
39        pieces.unflatten_ref()
40    }
41}
42
43impl AsMut<[[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2]> for ArchivedHistorySegment {
44    #[inline(always)]
45    fn as_mut(&mut self) -> &mut [[InnerPiece; RecordedHistorySegment::NUM_RAW_RECORDS]; 2] {
46        let pieces: &mut [InnerPiece; Self::NUM_PIECES] = self.as_mut();
47        pieces.unflatten_mut()
48    }
49}
50
51impl Deref for ArchivedHistorySegment {
52    type Target = [InnerPiece; Self::NUM_PIECES];
53
54    #[inline(always)]
55    fn deref(&self) -> &Self::Target {
56        self.as_ref()
57    }
58}
59
60impl DerefMut for ArchivedHistorySegment {
61    #[inline(always)]
62    fn deref_mut(&mut self) -> &mut Self::Target {
63        self.as_mut()
64    }
65}
66
67impl Default for ArchivedHistorySegment {
68    #[inline]
69    fn default() -> Self {
70        Self(FlatPieces::new(Self::NUM_PIECES))
71    }
72}
73
74const {
75    // Indexing with `PiecePosition` (a wrapper around `u8`) relies on every possible position
76    // having a corresponding piece
77    assert!(ArchivedHistorySegment::NUM_PIECES == usize::from(u8::MAX) + 1);
78}
79
80impl Index<PiecePosition> for ArchivedHistorySegment {
81    type Output = InnerPiece;
82
83    #[inline(always)]
84    fn index(&self, index: PiecePosition) -> &Self::Output {
85        self.get(usize::from(index)).expect(
86            "`PiecePosition` wraps `u8` and there are `u8::MAX + 1` pieces, checked above; qed",
87        )
88    }
89}
90
91impl IndexMut<PiecePosition> for ArchivedHistorySegment {
92    #[inline(always)]
93    fn index_mut(&mut self, index: PiecePosition) -> &mut Self::Output {
94        self.get_mut(usize::from(index)).expect(
95            "`PiecePosition` wraps `u8` and there are `u8::MAX + 1` pieces, checked above; qed",
96        )
97    }
98}
99
100impl ArchivedHistorySegment {
101    /// All records of this segment, split into source and parity halves
102    #[inline(always)]
103    pub fn split_records_mut(
104        &mut self,
105    ) -> (
106        [&mut Record; RecordedHistorySegment::NUM_RAW_RECORDS],
107        [&mut Record; RecordedHistorySegment::NUM_RAW_RECORDS],
108    ) {
109        let [source, parity]: &mut [[_; RecordedHistorySegment::NUM_RAW_RECORDS]; 2] =
110            self.as_mut();
111        let mut source = source.iter_mut().map(|piece| &mut piece.record);
112        let mut parity = parity.iter_mut().map(|piece| &mut piece.record);
113
114        (
115            array::from_fn(|_| {
116                source
117                    .next()
118                    .expect("Number of pieces matches the array size; qed")
119            }),
120            array::from_fn(|_| {
121                parity
122                    .next()
123                    .expect("Number of pieces matches the array size; qed")
124            }),
125        )
126    }
127
128    /// Number of pieces in one segment of archived history.
129    pub const NUM_PIECES: usize = RecordedHistorySegment::NUM_PIECES;
130    /// Size of archived history segment in bytes.
131    ///
132    /// It includes erasure coded [`InnerPiece`]s (both source and parity) that are
133    /// composed of [`crate::pieces::Record`]s together with corresponding roots and
134    /// proofs.
135    pub const SIZE: usize = Piece::SIZE * Self::NUM_PIECES;
136
137    /// Iterator over all pieces, see [`FlatPieces::pieces()`] for details
138    #[inline]
139    pub fn pieces(&self) -> Box<dyn ExactSizeIterator<Item = Piece> + '_> {
140        self.0.pieces()
141    }
142
143    /// Iterator over source pieces, see [`FlatPieces::source_pieces()`] for details
144    #[inline]
145    pub fn source_pieces(&self) -> impl ExactSizeIterator<Item = Piece> + '_ {
146        self.0.source_pieces()
147    }
148
149    /// Iterator over parity pieces, see [`FlatPieces::parity_pieces()`] for details
150    #[inline]
151    pub fn parity_pieces(&self) -> impl ExactSizeIterator<Item = Piece> + '_ {
152        self.0.parity_pieces()
153    }
154
155    /// Ensure archived history segment contains cheaply cloneable shared data.
156    ///
157    /// Internally archived history segment uses CoW mechanism and can store either mutable owned
158    /// data or data that is cheap to clone, calling this method will ensure further clones and
159    /// returned pieces will not result in additional memory allocations.
160    pub fn to_shared(self) -> Self {
161        Self(self.0.to_shared())
162    }
163}