use crate::err::BlobError;
use crate::in_stream::BlobStreamIn;
use crate::protocol::{AckChunkData, SetChunkData};
use crate::ChunkIndex;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Info {
pub total_octet_size: usize,
pub chunk_octet_size: usize,
pub chunk_count: usize,
pub chunk_count_received: usize,
pub waiting_for_chunk_index: ChunkIndex,
}
#[derive(Debug)]
pub struct Logic {
in_stream: BlobStreamIn,
}
impl Logic {
#[must_use]
pub fn new(octet_count: usize, chunk_size: usize) -> Self {
Self {
in_stream: BlobStreamIn::new(octet_count, chunk_size),
}
}
#[must_use]
pub fn info(&self) -> Info {
Info {
total_octet_size: self.in_stream.octet_count,
chunk_octet_size: self.in_stream.fixed_chunk_size,
chunk_count: self.in_stream.bit_array.bit_count(),
chunk_count_received: self.in_stream.bit_array.count_set_bits(),
waiting_for_chunk_index: self
.in_stream
.bit_array
.first_unset_bit()
.unwrap_or_else(|| self.in_stream.bit_array.bit_count()),
}
}
#[allow(clippy::cast_possible_truncation)]
pub fn receive(&mut self, chunk_data: &SetChunkData) -> Result<(), BlobError> {
self.in_stream
.set_chunk(chunk_data.chunk_index as ChunkIndex, &chunk_data.payload)
}
pub fn send(&mut self) -> AckChunkData {
let waiting_for_chunk_index = self
.in_stream
.bit_array
.first_unset_bit()
.unwrap_or_else(|| self.in_stream.bit_array.bit_count());
let receive_mask = self
.in_stream
.bit_array
.atom_from_index(waiting_for_chunk_index + 1);
AckChunkData {
waiting_for_chunk_index: waiting_for_chunk_index as u32,
receive_mask_after_last: receive_mask,
}
}
#[must_use]
pub fn blob(&self) -> Option<&[u8]> {
self.in_stream.blob()
}
#[must_use]
pub fn is_complete(&self) -> bool {
self.in_stream.is_complete()
}
}