use crate::{Doubling, Fragment, Growth, SplitVec};
use alloc::string::String;
use orx_pseudo_default::PseudoDefault;
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Recursive;
impl PseudoDefault for Recursive {
fn pseudo_default() -> Self {
Default::default()
}
}
impl Growth for Recursive {
#[inline(always)]
fn new_fragment_capacity_from(
&self,
fragment_capacities: impl ExactSizeIterator<Item = usize>,
) -> usize {
Doubling.new_fragment_capacity_from(fragment_capacities)
}
fn maximum_concurrent_capacity<T>(
&self,
fragments: &[Fragment<T>],
fragments_capacity: usize,
) -> usize {
assert!(fragments_capacity >= fragments.len());
let current_capacity = fragments.iter().map(|x| x.capacity()).sum();
let mut last_capacity = fragments.last().map(|x| x.capacity()).unwrap_or(2);
let mut total_capacity = current_capacity;
for _ in fragments.len()..fragments_capacity {
last_capacity *= 2;
total_capacity += last_capacity;
}
total_capacity
}
fn required_fragments_len<T>(
&self,
fragments: &[Fragment<T>],
maximum_capacity: usize,
) -> Result<usize, String> {
fn overflown_err() -> String {
alloc::format!(
"Maximum cumulative capacity that can be reached by the Recursive strategy is {}.",
usize::MAX
)
}
let current_capacity: usize = fragments.iter().map(|x| x.capacity()).sum();
let mut last_capacity = fragments.last().map(|x| x.capacity()).unwrap_or(2);
let mut total_capacity = current_capacity;
let mut f = fragments.len();
while total_capacity < maximum_capacity {
let (new_last_capacity, overflown) = last_capacity.overflowing_mul(2);
if overflown {
return Err(overflown_err());
}
last_capacity = new_last_capacity;
let (new_total_capacity, overflown) = total_capacity.overflowing_add(last_capacity);
if overflown {
return Err(overflown_err());
}
total_capacity = new_total_capacity;
f += 1;
}
Ok(f)
}
fn maximum_concurrent_capacity_bound<T>(
&self,
fragments: &[Fragment<T>],
fragments_capacity: usize,
) -> usize {
Doubling.maximum_concurrent_capacity_bound(fragments, fragments_capacity)
}
}
impl<T> SplitVec<T, Recursive> {
pub fn with_recursive_growth() -> Self {
SplitVec::with_doubling_growth().into()
}
pub fn with_recursive_growth_and_fragments_capacity(fragments_capacity: usize) -> Self {
SplitVec::with_doubling_growth_and_fragments_capacity(fragments_capacity).into()
}
pub fn with_recursive_growth_and_max_concurrent_capacity() -> Self {
SplitVec::with_doubling_growth_and_max_concurrent_capacity().into()
}
}