22use rand:: Rng ;
33
44use crate :: {
5- common:: { BOUNDARY_MARKER , RLNCError } ,
6- primitives:: {
7- Chunk ,
8- field:: { Field , Scalar } ,
9- packet:: RLNCPacket ,
10- } ,
5+ common:: RLNCError ,
6+ primitives:: { Chunks , field:: Field , packet:: RLNCPacket } ,
117} ;
128
13- /// RLNC encoder.
9+ /// RLNC encoder that's generic over the [`Field`] type. An ancoder should be instantiated
10+ /// per piece of data the caller wants to encode, then used to generate the encoded chunks.
1411#[ derive( Debug ) ]
1512pub struct Encoder < F : Field > {
1613 // The chunks of data to be encoded.
17- chunks : Vec < Chunk < F > > ,
14+ chunks : Chunks < F > ,
1815 // The number of chunks to split the data into (also known as the generation size).
1916 chunk_count : usize ,
2017 // The size of each chunk in bytes.
@@ -23,43 +20,18 @@ pub struct Encoder<F: Field> {
2320
2421impl < F : Field > Encoder < F > {
2522 /// Creates a new encoder for the given data and chunk count.
26- ///
27- /// # Arguments
28- ///
29- /// - `data` - The data to be encoded.
30- /// - `chunk_count` - The number of chunks to split the data into (also known as the generation
31- /// size).
3223 pub fn new ( data : impl AsRef < [ u8 ] > , chunk_count : usize ) -> Result < Self , RLNCError > {
33- if data. as_ref ( ) . is_empty ( ) {
34- return Err ( RLNCError :: EmptyData ) ;
35- }
36-
37- if chunk_count == 0 {
38- return Err ( RLNCError :: ZeroChunkCount ) ;
39- }
40-
41- let mut data = Vec :: from ( data. as_ref ( ) ) ;
42- data. push ( BOUNDARY_MARKER ) ;
43-
44- // Calculate chunk size to accommodate original data + boundary marker
45- let chunk_size = data. len ( ) . div_ceil ( chunk_count) ;
46-
47- // Round up chunk size to nearest multiple of `F::SAFE_CAPACITY` for scalar packing
48- let chunk_size = chunk_size. div_ceil ( F :: SAFE_CAPACITY ) * F :: SAFE_CAPACITY ;
49- let padded_len = chunk_size * chunk_count;
50-
51- // Pad the rest with zeros if needed
52- data. resize ( padded_len, 0 ) ;
53-
54- let chunks = data. chunks_exact ( chunk_size) . map ( Chunk :: from_bytes) . collect ( ) ;
24+ let chunks = Self :: prepare ( data, chunk_count) ?;
25+ let chunk_count = chunks. len ( ) ;
26+ let chunk_size = chunks. chunk_size ( ) ;
5527
5628 Ok ( Self { chunks, chunk_count, chunk_size } )
5729 }
5830
5931 /// Creates a new encoder from a vector of chunks.
60- pub fn from_chunks ( chunks : Vec < Chunk < F > > ) -> Self {
32+ pub fn from_chunks ( chunks : Chunks < F > ) -> Self {
6133 let chunk_count = chunks. len ( ) ;
62- let chunk_size = chunks[ 0 ] . size ( ) ;
34+ let chunk_size = chunks. chunk_size ( ) ;
6335
6436 Self { chunks, chunk_count, chunk_size }
6537 }
@@ -88,7 +60,7 @@ impl<F: Field> Encoder<F> {
8860 fn encode_inner ( & self , coding_vector : & [ F ] ) -> Vec < F > {
8961 let mut result = vec ! [ F :: ZERO ; self . chunk_size. div_ceil( F :: SAFE_CAPACITY ) ] ;
9062
91- for ( chunk, & coefficient) in self . chunks . iter ( ) . zip ( coding_vector) {
63+ for ( chunk, & coefficient) in self . chunks . inner ( ) . iter ( ) . zip ( coding_vector) {
9264 if coefficient. is_zero_vartime ( ) {
9365 continue ;
9466 }
@@ -113,32 +85,8 @@ impl<F: Field> Encoder<F> {
11385
11486 /// Prepares the data for encoding by splitting it into equally sized chunks and padding with
11587 /// zeros. Also converts the data into symbols in the chosen finite field.
116- pub fn prepare (
117- data : impl AsRef < [ u8 ] > ,
118- chunk_count : usize ,
119- ) -> Result < Vec < Chunk < Scalar > > , RLNCError > {
120- if data. as_ref ( ) . is_empty ( ) {
121- return Err ( RLNCError :: EmptyData ) ;
122- }
123-
124- if chunk_count == 0 {
125- return Err ( RLNCError :: ZeroChunkCount ) ;
126- }
127-
128- let mut data = Vec :: from ( data. as_ref ( ) ) ;
129- data. push ( BOUNDARY_MARKER ) ;
130-
131- // Calculate chunk size to accommodate original data + boundary marker
132- let chunk_size = data. len ( ) . div_ceil ( chunk_count) ;
133-
134- // Round up chunk size to nearest multiple of `F::SAFE_CAPACITY` for scalar packing
135- let chunk_size = chunk_size. div_ceil ( F :: SAFE_CAPACITY ) * F :: SAFE_CAPACITY ;
136- let padded_len = chunk_size * chunk_count;
137-
138- // Pad the rest with zeros if needed
139- data. resize ( padded_len, 0 ) ;
140-
141- Ok ( data. chunks_exact ( chunk_size) . map ( Chunk :: from_bytes) . collect ( ) )
88+ pub fn prepare ( data : impl AsRef < [ u8 ] > , chunk_count : usize ) -> Result < Chunks < F > , RLNCError > {
89+ Ok ( Chunks :: new ( data. as_ref ( ) , chunk_count) ?)
14290 }
14391
14492 /// Encodes the data with the given coding vector using linear combinations.
@@ -189,6 +137,7 @@ impl<F: Field> Encoder<F> {
189137 // Map each (chunk, coefficient) pair to its contribution and then reduce all
190138 // contributions into the final result.
191139 self . chunks
140+ . inner ( )
192141 . par_iter ( )
193142 . zip ( coding_vector)
194143 . filter_map ( |( chunk, & coefficient) | {
0 commit comments