use std::num::NonZero;
use bytes::Bytes;
use log::warn;
use crate::data::{Frame, Header};
#[derive(Debug)]
pub struct Transaction {
header: Header,
fragments: Vec<Option<Bytes>>,
}
impl Transaction {
#[must_use]
pub fn new(length: NonZero<u8>, header: Header, first_fragment: Bytes) -> Self {
let mut fragments = vec![None; length.get().into()];
fragments[0].replace(first_fragment);
Self { header, fragments }
}
pub fn insert(mut self, index: u8, fragment: Bytes) -> InsertResult {
let Some(slot) = self.fragments.get_mut(usize::from(index)) else {
return InsertResult::OutOfBounds(index);
};
if slot.replace(fragment).is_some() {
warn!("Duplicate fragment for index: {index}");
}
if self.fragments.iter().all(Option::is_some) {
self.header.drop_extended();
return InsertResult::Complete(Frame::raw(
self.header,
self.fragments
.into_iter()
.flat_map(|opt| opt.expect("All of the options are Some()."))
.collect(),
));
}
InsertResult::Incomplete(self)
}
}
#[derive(Debug)]
pub enum InsertResult {
Complete(Frame<Bytes>),
Incomplete(Transaction),
OutOfBounds(u8),
}