1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use super::{
    any,
    growth_trait::{SplitVecGrowth, SplitVecGrowthWithFlexibleIndexAccess},
};
use crate::{Fragment, SplitVec};
use std::{fmt::Debug, rc::Rc};

pub(crate) type GetCapacityOfNewFragment<T> = dyn Fn(&[Fragment<T>]) -> usize;

/// Stategy which allows to define a custom growth rate with a function
/// of priorly created fragments.
///
/// # Examples
///
/// ```
/// use orx_split_vec::prelude::*;
///
/// let mut vec = SplitVec::with_linear_growth(16);
///
/// for i in 0..10 * 16 {
///     vec.push(i);
/// }
///
/// assert_eq!(10, vec.fragments().len());
/// for fragment in vec.fragments() {
///     assert_eq!(16, fragment.len());
///     assert_eq!(16, fragment.capacity());
/// }
///
/// vec.push(42);
/// assert_eq!(11, vec.fragments().len());
/// assert_eq!(Some(16), vec.fragments().last().map(|f| f.capacity()));
/// assert_eq!(Some(1), vec.fragments().last().map(|f| f.len()));
/// ```
#[derive(Clone)]
pub struct CustomGrowth<T> {
    get_capacity_of_new_fragment: Rc<GetCapacityOfNewFragment<T>>,
}

impl<T> Debug for CustomGrowth<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("CustomGrowth").finish()
    }
}
impl<T> CustomGrowth<T> {
    /// Creates a new custom growth where the growth strategy is
    /// defined by the function `get_capacity_of_new_fragment`.
    ///
    /// # Panics
    /// Panics if the function returns 0 as the capacity of the new fragment
    /// for any given set of already created `fragments`.
    pub fn new(get_capacity_of_new_fragment: Rc<GetCapacityOfNewFragment<T>>) -> Self {
        Self {
            get_capacity_of_new_fragment,
        }
    }
}

impl<T: 'static> Default for CustomGrowth<T> {
    /// Creates the default custom growth which doubles the initial capacity every 4 fragments.
    ///
    /// Let c be the initial capacity of the split vector; i.e., capacity of the first fragment.
    /// Then, fragment capacities with the default function will be computed as:
    ///
    /// * capacities of fragments 0..4 = c
    /// * capacities of fragments 4..8 = 2c
    /// * capacities of fragments 8..12 = 3c
    /// * ...
    fn default() -> Self {
        fn default_exponential_growth<T>(fragments: &[Fragment<T>]) -> usize {
            let c = fragments.first().map(|f| f.capacity()).unwrap_or(4);
            let f = fragments.len();
            let m = (f / 4) as u32;
            c * usize::pow(2, m)
        }
        Self {
            get_capacity_of_new_fragment: Rc::new(default_exponential_growth::<T>),
        }
    }
}

impl<T> SplitVecGrowth<T> for CustomGrowth<T> {
    fn new_fragment_capacity(&self, fragments: &[Fragment<T>]) -> usize {
        let capacity = (self.get_capacity_of_new_fragment)(fragments);
        assert!(capacity > 0);
        capacity
    }
    fn get_fragment_and_inner_indices(
        &self,
        fragments: &[Fragment<T>],
        element_index: usize,
    ) -> Option<(usize, usize)> {
        any::get_fragment_and_inner_indices(fragments, element_index)
    }
}
impl<T> SplitVecGrowthWithFlexibleIndexAccess<T> for CustomGrowth<T> {}

impl<T> SplitVec<T, CustomGrowth<T>> {
    /// Creates a split vector with the custom grwoth strategy
    /// defined by the function `get_capacity_of_new_fragment`.
    ///
    /// # Examples
    /// ```
    /// use orx_split_vec::prelude::*;
    /// use std::rc::Rc;
    ///
    /// // vec: SplitVec<usize, CustomGrowth<usize>>
    /// let mut vec =
    ///     SplitVec::with_custom_growth_function(Rc::new(|fragments: &[Fragment<_>]| {
    ///         if fragments.len() % 2 == 0 {
    ///             2
    ///         } else {
    ///             8
    ///         }
    ///     }));
    ///
    ///     for i in 0..100 {
    ///         vec.push(i);
    ///     }
    ///
    ///     vec.into_iter().zip(0..100).all(|(l, r)| *l == r);
    ///     
    ///     for (f, fragment) in vec.fragments().iter().enumerate() {
    ///         if f % 2 == 0 {
    ///             assert_eq!(2, fragment.capacity());
    ///         } else {
    ///             assert_eq!(8, fragment.capacity());
    ///         }
    ///     }
    /// ```
    pub fn with_custom_growth_function(
        get_capacity_of_new_fragment: Rc<GetCapacityOfNewFragment<T>>,
    ) -> Self {
        let growth = CustomGrowth::new(get_capacity_of_new_fragment);
        Self {
            fragments: vec![],
            growth,
        }
    }
}