reed_solomon_simd/rate/
encoder_work.rs

1use crate::{
2    engine::{Shards, ShardsRefMut},
3    Error,
4};
5
6// ======================================================================
7// EncoderWork - PUBLIC
8
9/// Working space for [`RateEncoder`].
10///
11/// [`RateEncoder`]: crate::rate::RateEncoder
12pub struct EncoderWork {
13    original_count: usize,
14    recovery_count: usize,
15
16    pub(crate) shard_bytes: usize,
17
18    original_received_count: usize,
19    shards: Shards,
20}
21
22impl EncoderWork {
23    /// Creates new [`EncoderWork`] which initially
24    /// has no working space allocated.
25    pub fn new() -> Self {
26        Self {
27            original_count: 0,
28            recovery_count: 0,
29            shard_bytes: 0,
30
31            original_received_count: 0,
32            shards: Shards::new(),
33        }
34    }
35}
36
37// ======================================================================
38// EncoderWork - IMPL Default
39
40impl Default for EncoderWork {
41    fn default() -> Self {
42        Self::new()
43    }
44}
45
46// ======================================================================
47// EncoderWork - CRATE
48
49impl EncoderWork {
50    pub(crate) fn add_original_shard<T: AsRef<[u8]>>(
51        &mut self,
52        original_shard: T,
53    ) -> Result<(), Error> {
54        let original_shard = original_shard.as_ref();
55
56        if self.original_received_count == self.original_count {
57            Err(Error::TooManyOriginalShards {
58                original_count: self.original_count,
59            })
60        } else if original_shard.len() != self.shard_bytes {
61            Err(Error::DifferentShardSize {
62                shard_bytes: self.shard_bytes,
63                got: original_shard.len(),
64            })
65        } else {
66            self.shards
67                .insert(self.original_received_count, original_shard);
68
69            self.original_received_count += 1;
70            Ok(())
71        }
72    }
73
74    pub(crate) fn encode_begin(&mut self) -> Result<(ShardsRefMut, usize, usize), Error> {
75        if self.original_received_count == self.original_count {
76            Ok((
77                self.shards.as_ref_mut(),
78                self.original_count,
79                self.recovery_count,
80            ))
81        } else {
82            Err(Error::TooFewOriginalShards {
83                original_count: self.original_count,
84                original_received_count: self.original_received_count,
85            })
86        }
87    }
88
89    // This must only be called by `EncoderResult`.
90    pub(crate) fn recovery(&self, index: usize) -> Option<&[u8]> {
91        if index < self.recovery_count {
92            Some(&self.shards[index].as_flattened()[..self.shard_bytes])
93        } else {
94            None
95        }
96    }
97
98    pub(crate) fn reset(
99        &mut self,
100        original_count: usize,
101        recovery_count: usize,
102        shard_bytes: usize,
103        work_count: usize,
104    ) {
105        assert!(shard_bytes % 2 == 0);
106
107        self.original_count = original_count;
108        self.recovery_count = recovery_count;
109        self.shard_bytes = shard_bytes;
110
111        self.original_received_count = 0;
112        self.shards.resize(work_count, shard_bytes.div_ceil(64));
113    }
114
115    pub(crate) fn reset_received(&mut self) {
116        self.original_received_count = 0;
117    }
118
119    pub(crate) fn undo_last_chunk_encoding(&mut self) {
120        self.shards
121            .undo_last_chunk_encoding(self.shard_bytes, 0..self.recovery_count);
122    }
123}