1#[cfg(feature = "std")]
2use std::{cmp::min, vec::Vec};
3
4#[cfg(not(feature = "std"))]
5use core::cmp::min;
6
7#[cfg(not(feature = "std"))]
8use alloc::vec::Vec;
9
10use crate::rng::rand;
11use crate::systematic_constants::{
12 MAX_SOURCE_SYMBOLS_PER_BLOCK, SYSTEMATIC_INDICES_AND_PARAMETERS,
13};
14use crate::util::int_div_ceil;
15#[cfg(feature = "serde_support")]
16use serde::{Deserialize, Serialize};
17
18#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
20#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
21pub struct PayloadId {
22 source_block_number: u8,
23 encoding_symbol_id: u32,
24}
25
26impl PayloadId {
27 pub fn new(source_block_number: u8, encoding_symbol_id: u32) -> PayloadId {
28 assert!(encoding_symbol_id < 16777216);
30 PayloadId {
31 source_block_number,
32 encoding_symbol_id,
33 }
34 }
35
36 #[allow(clippy::trivially_copy_pass_by_ref)]
37 pub fn deserialize(data: &[u8; 4]) -> PayloadId {
38 PayloadId {
39 source_block_number: data[0],
40 encoding_symbol_id: ((data[1] as u32) << 16) + ((data[2] as u32) << 8) + data[3] as u32,
41 }
42 }
43
44 pub fn serialize(&self) -> [u8; 4] {
45 [
46 self.source_block_number,
47 (self.encoding_symbol_id >> 16) as u8,
48 ((self.encoding_symbol_id >> 8) & 0xFF) as u8,
49 (self.encoding_symbol_id & 0xFF) as u8,
50 ]
51 }
52
53 pub fn source_block_number(&self) -> u8 {
54 self.source_block_number
55 }
56
57 pub fn encoding_symbol_id(&self) -> u32 {
58 self.encoding_symbol_id
59 }
60}
61
62#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
66#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
67pub struct EncodingPacket {
68 pub(crate) payload_id: PayloadId,
69 pub(crate) data: Vec<u8>,
70}
71
72impl EncodingPacket {
73 pub fn new(payload_id: PayloadId, data: Vec<u8>) -> EncodingPacket {
74 EncodingPacket { payload_id, data }
75 }
76
77 pub fn deserialize(data: &[u8]) -> EncodingPacket {
78 let payload_data = [data[0], data[1], data[2], data[3]];
79 EncodingPacket {
80 payload_id: PayloadId::deserialize(&payload_data),
81 data: Vec::from(&data[4..]),
82 }
83 }
84
85 pub fn serialize(&self) -> Vec<u8> {
86 let mut serialized = Vec::with_capacity(4 + self.data.len());
87 serialized.extend_from_slice(&self.payload_id.serialize());
88 serialized.extend(self.data.iter());
89 return serialized;
90 }
91
92 pub fn payload_id(&self) -> &PayloadId {
94 &self.payload_id
95 }
96
97 pub fn data(&self) -> &[u8] {
99 &self.data
100 }
101
102 pub fn split(self) -> (PayloadId, Vec<u8>) {
104 (self.payload_id, self.data)
105 }
106}
107
108#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
110#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
111pub struct ObjectTransmissionInformation {
112 transfer_length: u64, symbol_size: u16,
114 num_source_blocks: u8,
115 num_sub_blocks: u16,
116 symbol_alignment: u8,
117}
118
119impl ObjectTransmissionInformation {
120 pub fn new(
121 transfer_length: u64,
122 symbol_size: u16,
123 source_blocks: u8,
124 sub_blocks: u16,
125 alignment: u8,
126 ) -> ObjectTransmissionInformation {
127 assert!(transfer_length <= 942574504275);
129 assert_eq!(symbol_size % alignment as u16, 0);
130 if (symbol_size != 0) && (source_blocks != 0) {
133 let symbols_required = int_div_ceil(
134 int_div_ceil(transfer_length, symbol_size as u64) as u64,
135 source_blocks as u64,
136 );
137 assert!((symbols_required) <= MAX_SOURCE_SYMBOLS_PER_BLOCK);
138 }
139
140 ObjectTransmissionInformation {
141 transfer_length,
142 symbol_size,
143 num_source_blocks: source_blocks,
144 num_sub_blocks: sub_blocks,
145 symbol_alignment: alignment,
146 }
147 }
148
149 pub fn deserialize(data: &[u8; 12]) -> ObjectTransmissionInformation {
150 ObjectTransmissionInformation {
151 transfer_length: ((data[0] as u64) << 32)
152 + ((data[1] as u64) << 24)
153 + ((data[2] as u64) << 16)
154 + ((data[3] as u64) << 8)
155 + (data[4] as u64),
156 symbol_size: ((data[6] as u16) << 8) + data[7] as u16,
157 num_source_blocks: data[8],
158 num_sub_blocks: ((data[9] as u16) << 8) + data[10] as u16,
159 symbol_alignment: data[11],
160 }
161 }
162
163 pub fn serialize(&self) -> [u8; 12] {
164 [
165 ((self.transfer_length >> 32) & 0xFF) as u8,
166 ((self.transfer_length >> 24) & 0xFF) as u8,
167 ((self.transfer_length >> 16) & 0xFF) as u8,
168 ((self.transfer_length >> 8) & 0xFF) as u8,
169 (self.transfer_length & 0xFF) as u8,
170 0, (self.symbol_size >> 8) as u8,
172 (self.symbol_size & 0xFF) as u8,
173 self.num_source_blocks,
174 (self.num_sub_blocks >> 8) as u8,
175 (self.num_sub_blocks & 0xFF) as u8,
176 self.symbol_alignment,
177 ]
178 }
179
180 pub fn transfer_length(&self) -> u64 {
181 self.transfer_length
182 }
183
184 pub fn symbol_size(&self) -> u16 {
185 self.symbol_size
186 }
187
188 pub fn source_blocks(&self) -> u8 {
189 self.num_source_blocks
190 }
191
192 pub fn sub_blocks(&self) -> u16 {
193 self.num_sub_blocks
194 }
195
196 pub fn symbol_alignment(&self) -> u8 {
197 self.symbol_alignment
198 }
199
200 pub(crate) fn generate_encoding_parameters(
201 transfer_length: u64,
202 max_packet_size: u16,
203 decoder_memory_requirement: u64,
204 ) -> ObjectTransmissionInformation {
205 let (alignment, sub_symbol_size) = if max_packet_size >= 8 * 8 {
206 (8, 8)
207 } else {
208 (1, 1)
209 };
210 assert!(max_packet_size >= alignment);
211 let symbol_size = max_packet_size - (max_packet_size % alignment);
212
213 let kt = int_div_ceil(transfer_length, symbol_size as u64);
214
215 let n_max = symbol_size as u32 / (sub_symbol_size * alignment) as u32;
216
217 let kl = |n: u32| -> u32 {
218 for &(kprime, _, _, _, _) in SYSTEMATIC_INDICES_AND_PARAMETERS.iter().rev() {
219 let x = int_div_ceil(symbol_size as u64, alignment as u64 * n as u64);
220 if kprime <= (decoder_memory_requirement / (alignment as u64 * x as u64)) as u32 {
221 return kprime;
222 }
223 }
224 unreachable!();
225 };
226
227 let num_source_blocks = int_div_ceil(kt as u64, kl(n_max) as u64);
228
229 let mut n = 1;
230 for i in 1..=n_max {
231 n = i;
232 if int_div_ceil(kt as u64, num_source_blocks as u64) <= kl(n) {
233 break;
234 }
235 }
236
237 ObjectTransmissionInformation {
238 transfer_length,
239 symbol_size,
240 num_source_blocks: num_source_blocks as u8,
241 num_sub_blocks: n as u16,
242 symbol_alignment: alignment as u8,
243 }
244 }
245
246 pub fn with_defaults(
247 transfer_length: u64,
248 max_packet_size: u16,
249 ) -> ObjectTransmissionInformation {
250 ObjectTransmissionInformation::generate_encoding_parameters(
251 transfer_length,
252 max_packet_size,
253 10 * 1024 * 1024,
254 )
255 }
256}
257
258pub fn partition<TI, TJ>(i: TI, j: TJ) -> (u32, u32, u32, u32)
260where
261 TI: Into<u32>,
262 TJ: Into<u32>,
263{
264 let (i, j) = (i.into(), j.into());
265 let il = int_div_ceil(i as u64, j as u64);
266
267 let is = i / j;
268
269 let jl = i - is * j;
270 let js = j - jl;
271 (il, is, jl, js)
272}
273
274pub fn deg(v: u32, lt_symbols: u32) -> u32 {
276 assert!(v < 1048576);
277 let f: [u32; 31] = [
278 0, 5243, 529531, 704294, 791675, 844104, 879057, 904023, 922747, 937311, 948962, 958494,
279 966438, 973160, 978921, 983914, 988283, 992138, 995565, 998631, 1001391, 1003887, 1006157,
280 1008229, 1010129, 1011876, 1013490, 1014983, 1016370, 1017662, 1048576,
281 ];
282
283 #[allow(clippy::needless_range_loop)]
284 for d in 1..f.len() {
285 if v < f[d] {
286 return min(d as u32, lt_symbols - 2);
287 }
288 }
289 unreachable!();
290}
291
292#[allow(non_snake_case, clippy::many_single_char_names)]
294pub fn intermediate_tuple(
295 internal_symbol_id: u32,
296 lt_symbols: u32,
297 systematic_index: u32,
298 p1: u32,
299) -> (u32, u32, u32, u32, u32, u32) {
300 let J = systematic_index;
301 let W = lt_symbols;
302 let P1 = p1;
303
304 let mut A = 53591 + J * 997;
305
306 if A % 2 == 0 {
307 A += 1;
308 }
309
310 let B = 10267 * (J + 1);
311 let y: u32 = ((B as u64 + internal_symbol_id as u64 * A as u64) % 4294967296) as u32;
312 let v = rand(y, 0u32, 1048576);
313 let d = deg(v, W);
314 let a = 1 + rand(y, 1u32, W - 1);
315 let b = rand(y, 2u32, W);
316
317 let d1 = if d < 4 {
318 2 + rand(internal_symbol_id, 3u32, 2)
319 } else {
320 2
321 };
322
323 let a1 = 1 + rand(internal_symbol_id, 4u32, P1 - 1);
324 let b1 = rand(internal_symbol_id, 5u32, P1);
325
326 (d, a, b, d1, a1, b1)
327}
328
329#[cfg(test)]
330mod tests {
331 use crate::{EncodingPacket, ObjectTransmissionInformation, PayloadId};
332 use rand::Rng;
333
334 #[test]
335 fn max_transfer_size() {
336 ObjectTransmissionInformation::new(942574504275, 65535, 255, 1, 1);
337 }
338
339 #[test]
340 fn payload_id_serialization() {
341 let payload_id = PayloadId::new(
342 rand::thread_rng().gen(),
343 rand::thread_rng().gen_range(0..(256 * 256 * 256)),
344 );
345 let deserialized = PayloadId::deserialize(&payload_id.serialize());
346 assert_eq!(deserialized, payload_id);
347 }
348
349 #[test]
350 fn encoding_packet_serialization() {
351 let payload_id = PayloadId::new(
352 rand::thread_rng().gen(),
353 rand::thread_rng().gen_range(0..(256 * 256 * 256)),
354 );
355 let packet = EncodingPacket::new(payload_id, vec![rand::thread_rng().gen()]);
356 let deserialized = EncodingPacket::deserialize(&packet.serialize());
357 assert_eq!(deserialized, packet);
358 }
359
360 #[test]
361 fn oti_serialization() {
362 let oti = ObjectTransmissionInformation::with_defaults(
363 rand::thread_rng().gen_range(0..(256 * 256 * 256 * 256 * 256)),
364 rand::thread_rng().gen(),
365 );
366 let deserialized = ObjectTransmissionInformation::deserialize(&oti.serialize());
367 assert_eq!(deserialized, oti);
368 }
369}