reed_solomon_simd/rate/
encoder_work.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::{
    engine::{Shards, ShardsRefMut},
    Error,
};

// ======================================================================
// EncoderWork - PUBLIC

/// Working space for [`RateEncoder`].
///
/// [`RateEncoder`]: crate::rate::RateEncoder
pub struct EncoderWork {
    original_count: usize,
    recovery_count: usize,

    pub(crate) shard_bytes: usize,

    original_received_count: usize,
    shards: Shards,
}

impl EncoderWork {
    /// Creates new [`EncoderWork`] which initially
    /// has no working space allocated.
    pub fn new() -> Self {
        Self {
            original_count: 0,
            recovery_count: 0,
            shard_bytes: 0,

            original_received_count: 0,
            shards: Shards::new(),
        }
    }
}

// ======================================================================
// EncoderWork - IMPL Default

impl Default for EncoderWork {
    fn default() -> Self {
        Self::new()
    }
}

// ======================================================================
// EncoderWork - CRATE

impl EncoderWork {
    pub(crate) fn add_original_shard<T: AsRef<[u8]>>(
        &mut self,
        original_shard: T,
    ) -> Result<(), Error> {
        let original_shard = original_shard.as_ref();

        if self.original_received_count == self.original_count {
            Err(Error::TooManyOriginalShards {
                original_count: self.original_count,
            })
        } else if original_shard.len() != self.shard_bytes {
            Err(Error::DifferentShardSize {
                shard_bytes: self.shard_bytes,
                got: original_shard.len(),
            })
        } else {
            self.shards
                .insert(self.original_received_count, original_shard);

            self.original_received_count += 1;
            Ok(())
        }
    }

    pub(crate) fn encode_begin(&mut self) -> Result<(ShardsRefMut, usize, usize), Error> {
        if self.original_received_count == self.original_count {
            Ok((
                self.shards.as_ref_mut(),
                self.original_count,
                self.recovery_count,
            ))
        } else {
            Err(Error::TooFewOriginalShards {
                original_count: self.original_count,
                original_received_count: self.original_received_count,
            })
        }
    }

    // This must only be called by `EncoderResult`.
    pub(crate) fn recovery(&self, index: usize) -> Option<&[u8]> {
        if index < self.recovery_count {
            Some(&self.shards[index].as_flattened()[..self.shard_bytes])
        } else {
            None
        }
    }

    pub(crate) fn reset(
        &mut self,
        original_count: usize,
        recovery_count: usize,
        shard_bytes: usize,
        work_count: usize,
    ) {
        assert!(shard_bytes % 2 == 0);

        self.original_count = original_count;
        self.recovery_count = recovery_count;
        self.shard_bytes = shard_bytes;

        self.original_received_count = 0;
        self.shards.resize(work_count, shard_bytes.div_ceil(64));
    }

    pub(crate) fn reset_received(&mut self) {
        self.original_received_count = 0;
    }

    pub(crate) fn undo_last_chunk_encoding(&mut self) {
        self.shards
            .undo_last_chunk_encoding(self.shard_bytes, 0..self.recovery_count);
    }
}