blob_stream/
out_logic.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/nimble-rust/nimble
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use crate::out_stream::{BlobStreamOut, OutStreamError};
6use crate::prelude::{SetChunkData, SetChunkFrontData, TransferId};
7use std::time::{Duration, Instant};
8
9#[allow(unused)]
10#[derive(Debug)]
11pub struct Logic {
12    out_stream: BlobStreamOut,
13    blob: Vec<u8>,
14    fixed_chunk_size: usize,
15    transfer_id: TransferId,
16}
17
18impl Logic {
19    pub fn new(
20        transfer_id: TransferId,
21        fixed_chunk_size: usize,
22        resend_duration: Duration,
23        blob: &[u8],
24    ) -> Self {
25        let chunk_count = blob.len().div_ceil(fixed_chunk_size);
26        Self {
27            out_stream: BlobStreamOut::new(chunk_count, resend_duration),
28            blob: blob.to_vec(),
29            transfer_id,
30            fixed_chunk_size,
31        }
32    }
33
34    #[inline]
35    fn get_range(&self, index: usize) -> (usize, usize) {
36        assert!(index < self.blob.len(), "out logic index out of bounds");
37        let start = index * self.fixed_chunk_size;
38        let is_last_chunk = index + 1 == self.out_stream.chunk_count();
39        let count = if is_last_chunk {
40            let remaining_size = self.blob.len() % self.fixed_chunk_size;
41            if remaining_size == 0 {
42                self.fixed_chunk_size
43            } else {
44                remaining_size
45            }
46        } else {
47            self.fixed_chunk_size
48        };
49
50        (start, start + count)
51    }
52
53    #[must_use]
54    pub fn send(&mut self, now: Instant, max_count: usize) -> Vec<SetChunkFrontData> {
55        let indices = self.out_stream.send(now, max_count);
56        let mut set_chunks = Vec::new();
57        for chunk_index in indices {
58            let (start, end) = self.get_range(chunk_index);
59            let payload = &self.blob[start..end];
60            let set_chunk = SetChunkFrontData {
61                transfer_id: self.transfer_id,
62                data: SetChunkData {
63                    chunk_index: chunk_index as u32,
64                    payload: payload.to_vec(),
65                },
66            };
67            set_chunks.push(set_chunk);
68        }
69        set_chunks
70    }
71
72    pub fn set_waiting_for_chunk_index(
73        &mut self,
74        waiting_for_index: usize,
75        receive_mask: u64,
76    ) -> Result<(), OutStreamError> {
77        self.out_stream
78            .set_waiting_for_chunk_index(waiting_for_index, receive_mask)
79    }
80
81    #[must_use]
82    pub fn is_received_by_remote(&self) -> bool {
83        self.out_stream.is_received_by_remote()
84    }
85
86    #[must_use]
87    pub fn octet_size(&self) -> usize {
88        self.blob.len()
89    }
90
91    #[must_use]
92    pub fn chunk_size(&self) -> usize {
93        self.fixed_chunk_size
94    }
95
96    #[must_use]
97    pub fn transfer_id(&self) -> TransferId {
98        self.transfer_id
99    }
100}