reed_solomon_erasure/
macros.rs

1/// Constructs vector of shards.
2///
3/// # Example
4/// ```rust
5/// # #[macro_use] extern crate reed_solomon_erasure;
6/// # use reed_solomon_erasure::*;
7/// # fn main () {
8/// let shards: Vec<Vec<u8>> = shards!([1, 2, 3],
9///                                    [4, 5, 6]);
10/// # }
11/// ```
12#[macro_export]
13macro_rules! shards {
14    (
15        $( [ $( $x:expr ),* ] ),*
16    ) => {{
17        vec![ $( vec![ $( $x ),* ] ),* ]
18    }}
19}
20
21/// Makes it easier to work with 2D slices, arrays, etc.
22///
23/// # Examples
24/// ## Byte arrays on stack to `Vec<&[u8]>`
25/// ```rust
26/// # #[macro_use] extern crate reed_solomon_erasure;
27/// # fn main () {
28/// let array: [[u8; 3]; 2] = [[1, 2, 3],
29///                             [4, 5, 6]];
30///
31/// let refs: Vec<&[u8]> =
32///     convert_2D_slices!(array =>to_vec &[u8]);
33/// # }
34/// ```
35/// ## Byte arrays on stack to `Vec<&mut [u8]>` (borrow mutably)
36/// ```rust
37/// # #[macro_use] extern crate reed_solomon_erasure;
38/// # fn main () {
39/// let mut array: [[u8; 3]; 2] = [[1, 2, 3],
40///                                [4, 5, 6]];
41///
42/// let refs: Vec<&mut [u8]> =
43///     convert_2D_slices!(array =>to_mut_vec &mut [u8]);
44/// # }
45/// ```
46/// ## Byte arrays on stack to `SmallVec<[&mut [u8]; 32]>` (borrow mutably)
47/// ```rust
48/// # #[macro_use] extern crate reed_solomon_erasure;
49/// # extern crate smallvec;
50/// # use smallvec::SmallVec;
51/// # fn main () {
52/// let mut array: [[u8; 3]; 2] = [[1, 2, 3],
53///                                [4, 5, 6]];
54///
55/// let refs: SmallVec<[&mut [u8]; 32]> =
56///     convert_2D_slices!(array =>to_mut SmallVec<[&mut [u8]; 32]>,
57///                        SmallVec::with_capacity);
58/// # }
59/// ```
60/// ## Shard array to `SmallVec<[&mut [u8]; 32]>` (borrow mutably)
61/// ```rust
62/// # #[macro_use] extern crate reed_solomon_erasure;
63/// # extern crate smallvec;
64/// # use smallvec::SmallVec;
65/// # fn main () {
66/// let mut shards = shards!([1, 2, 3],
67///                          [4, 5, 6]);
68///
69/// let refs: SmallVec<[&mut [u8]; 32]> =
70///     convert_2D_slices!(shards =>to_mut SmallVec<[&mut [u8]; 32]>,
71///                        SmallVec::with_capacity);
72/// # }
73/// ```
74/// ## Shard array to `Vec<&mut [u8]>` (borrow mutably) into `SmallVec<[&mut [u8]; 32]>` (move)
75/// ```rust
76/// # #[macro_use] extern crate reed_solomon_erasure;
77/// # extern crate smallvec;
78/// # use smallvec::SmallVec;
79/// # fn main () {
80/// let mut shards = shards!([1, 2, 3],
81///                          [4, 5, 6]);
82///
83/// let refs1 = convert_2D_slices!(shards =>to_mut_vec &mut [u8]);
84///
85/// let refs2: SmallVec<[&mut [u8]; 32]> =
86///     convert_2D_slices!(refs1 =>into SmallVec<[&mut [u8]; 32]>,
87///                        SmallVec::with_capacity);
88/// # }
89/// ```
90#[macro_export]
91macro_rules! convert_2D_slices {
92    (
93        $slice:expr =>into_vec $dst_type:ty
94    ) => {
95        convert_2D_slices!($slice =>into Vec<$dst_type>,
96                           Vec::with_capacity)
97    };
98    (
99        $slice:expr =>to_vec $dst_type:ty
100    ) => {
101        convert_2D_slices!($slice =>to Vec<$dst_type>,
102                           Vec::with_capacity)
103    };
104    (
105        $slice:expr =>to_mut_vec $dst_type:ty
106    ) => {
107        convert_2D_slices!($slice =>to_mut Vec<$dst_type>,
108                           Vec::with_capacity)
109    };
110    (
111        $slice:expr =>into $dst_type:ty, $with_capacity:path
112    ) => {{
113        let mut result: $dst_type =
114            $with_capacity($slice.len());
115        for i in $slice.into_iter() {
116            result.push(i);
117        }
118        result
119    }};
120    (
121        $slice:expr =>to $dst_type:ty, $with_capacity:path
122    ) => {{
123        let mut result: $dst_type =
124            $with_capacity($slice.len());
125        for i in $slice.iter() {
126            result.push(i);
127        }
128        result
129    }};
130    (
131        $slice:expr =>to_mut $dst_type:ty, $with_capacity:path
132    ) => {{
133        let mut result: $dst_type =
134            $with_capacity($slice.len());
135        for i in $slice.iter_mut() {
136            result.push(i);
137        }
138        result
139    }}
140}
141
142macro_rules! check_slices {
143    (
144        multi => $slices:expr
145    ) => {{
146        let size = $slices[0].as_ref().len();
147        if size == 0 {
148            return Err(Error::EmptyShard);
149        }
150        for slice in $slices.iter() {
151            if slice.as_ref().len() != size {
152                return Err(Error::IncorrectShardSize);
153            }
154        }
155    }};
156    (
157        single => $slice_left:expr, single => $slice_right:expr
158    ) => {{
159        if $slice_left.as_ref().len() != $slice_right.as_ref().len() {
160            return Err(Error::IncorrectShardSize);
161        }
162    }};
163    (
164        multi => $slices:expr, single => $single:expr
165    ) => {{
166        check_slices!(multi => $slices);
167
168        check_slices!(single => $slices[0], single => $single);
169    }};
170    (
171        multi => $slices_left:expr, multi => $slices_right:expr
172    ) => {{
173        check_slices!(multi => $slices_left);
174        check_slices!(multi => $slices_right);
175
176        check_slices!(single => $slices_left[0], single => $slices_right[0]);
177    }}
178}
179
180macro_rules! check_slice_index {
181    (
182        all => $codec:expr, $index:expr
183    ) => {{
184        if $index >= $codec.total_shard_count {
185            return Err(Error::InvalidIndex);
186        }
187    }};
188    (
189        data => $codec:expr, $index:expr
190    ) => {{
191        if $index >= $codec.data_shard_count {
192            return Err(Error::InvalidIndex);
193        }
194    }};
195    (
196        parity => $codec:expr, $index:expr
197    ) => {{
198        if $index >= $codec.parity_shard_count {
199            return Err(Error::InvalidIndex);
200        }
201    }};
202}
203
204macro_rules! check_piece_count {
205    (
206        all => $codec:expr, $pieces:expr
207    ) => {{
208        if $pieces.as_ref().len() < $codec.total_shard_count {
209            return Err(Error::TooFewShards);
210        }
211        if $pieces.as_ref().len() > $codec.total_shard_count {
212            return Err(Error::TooManyShards);
213        }
214    }};
215    (
216        data => $codec:expr, $pieces:expr
217    ) => {{
218        if $pieces.as_ref().len() < $codec.data_shard_count {
219            return Err(Error::TooFewDataShards);
220        }
221        if $pieces.as_ref().len() > $codec.data_shard_count {
222            return Err(Error::TooManyDataShards);
223        }
224    }};
225    (
226        parity => $codec:expr, $pieces:expr
227    ) => {{
228        if $pieces.as_ref().len() < $codec.parity_shard_count {
229            return Err(Error::TooFewParityShards);
230        }
231        if $pieces.as_ref().len() > $codec.parity_shard_count {
232            return Err(Error::TooManyParityShards);
233        }
234    }};
235    (
236        parity_buf => $codec:expr, $pieces:expr
237    ) => {{
238        if $pieces.as_ref().len() < $codec.parity_shard_count {
239            return Err(Error::TooFewBufferShards);
240        }
241        if $pieces.as_ref().len() > $codec.parity_shard_count {
242            return Err(Error::TooManyBufferShards);
243        }
244    }};
245}