use alloc::vec::Vec;
#[derive(Default)]
pub struct Fragment<T> {
pub(crate) data: Vec<T>,
}
impl<T> Fragment<T> {
pub fn new_with_first_value(capacity: usize, first_value: T) -> Self {
let mut data = Vec::with_capacity(capacity);
data.push(first_value);
Self { data }
}
pub fn new(capacity: usize) -> Self {
Self {
data: Vec::with_capacity(capacity),
}
}
pub fn new_filled<F: Fn() -> T>(capacity: usize, f: F) -> Self {
let mut data = Vec::with_capacity(capacity);
for _ in 0..capacity {
data.push(f());
}
Self { data }
}
pub fn has_capacity_for_one(&self) -> bool {
self.data.len() < self.data.capacity()
}
pub fn room(&self) -> usize {
self.data.capacity() - self.data.len()
}
pub(crate) fn fragments_with_default_capacity() -> Vec<Fragment<T>> {
Vec::new()
}
pub(crate) fn into_fragments(self) -> Vec<Fragment<T>> {
let mut fragments = Self::fragments_with_default_capacity();
fragments.push(self);
fragments
}
pub(crate) fn fragments_with_capacity(fragments_capacity: usize) -> Vec<Fragment<T>> {
Vec::with_capacity(fragments_capacity)
}
pub(crate) fn into_fragments_with_capacity(
self,
fragments_capacity: usize,
) -> Vec<Fragment<T>> {
let mut fragments = Self::fragments_with_capacity(fragments_capacity);
fragments.push(self);
fragments
}
#[inline(always)]
pub(crate) unsafe fn zero(&mut self) {
let slice = core::slice::from_raw_parts_mut(self.data.as_mut_ptr(), self.capacity());
slice.iter_mut().for_each(|m| *m = core::mem::zeroed());
}
}
pub(crate) unsafe fn set_fragments_len<T>(fragments: &mut [Fragment<T>], len: usize) {
let mut remaining = len;
for fragment in fragments {
let capacity = fragment.capacity();
match remaining <= capacity {
true => {
fragment.set_len(remaining);
remaining = 0;
}
false => {
fragment.set_len(capacity);
remaining -= capacity;
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn zeroed() {
let mut fragment: Fragment<i32> = Fragment::new(4);
unsafe { fragment.zero() };
unsafe { fragment.set_len(4) };
let zero: i32 = unsafe { core::mem::zeroed() };
for i in 0..4 {
assert_eq!(fragment.get(i), Some(&zero));
}
}
}