osom_lib_arrays/immutable_array/
immutable_array_builder.rs1#![allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_sign_loss)]
2
3use osom_lib_alloc::Allocator;
4use osom_lib_primitives::Length;
5
6#[cfg(feature = "std_alloc")]
7use osom_lib_alloc::StdAllocator;
8
9use crate::errors::ArrayConstructionError;
10
11use super::internal_array::{InternalArray, MAX_LENGTH};
12use super::{ImmutableArray, ImmutableWeakArray};
13
14const INITIAL_CAPACITY: Length = unsafe { Length::new_unchecked(16) };
15
16pub struct ImmutableArrayBuilder<
23 T: Sized,
24 #[cfg(feature = "std_alloc")] TAllocator = StdAllocator,
25 #[cfg(not(feature = "std_alloc"))] TAllocator,
26> where
27 TAllocator: Allocator,
28{
29 internal: InternalArray<T, TAllocator>,
30}
31
32impl<T: Sized, TAllocator: Allocator> ImmutableArrayBuilder<T, TAllocator> {
33 #[inline(always)]
34 const fn grow_formula(current: usize) -> Length {
35 unsafe { Length::new_unchecked((3 * (current / 2)) as i32) }
36 }
37
38 pub fn shrink_to_fit(&mut self) -> Result<(), ArrayConstructionError> {
48 let internal = &mut self.internal;
49 let internal_len = internal.len();
50 let internal_capacity = internal.capacity();
51 if internal_len == internal_capacity {
52 return Ok(());
53 }
54
55 let mut new_internal: InternalArray<T, TAllocator> =
56 InternalArray::allocate(internal_len, internal_len, internal.allocator().clone())?;
57 let heap_data = new_internal.heap_data_mut();
58 let data_ptr = heap_data.data().as_ptr();
59 unsafe {
60 data_ptr.copy_from_nonoverlapping(internal.heap_data().data().as_ptr(), internal_len.value() as usize);
61 }
62 self.internal = new_internal;
63 Ok(())
64 }
65
66 #[inline(always)]
73 pub fn build(self) -> ImmutableArray<T, TAllocator> {
74 let internal = unsafe { core::ptr::read(&self.internal) };
75 core::mem::forget(self);
76 ImmutableArray::from(internal)
77 }
78
79 #[inline(always)]
85 pub fn new() -> Result<Self, ArrayConstructionError> {
86 Self::with_allocator(TAllocator::default())
87 }
88
89 #[inline(always)]
95 pub fn with_allocator(allocator: TAllocator) -> Result<Self, ArrayConstructionError> {
96 let internal = InternalArray::allocate(Length::ZERO, INITIAL_CAPACITY, allocator)?;
97 Ok(Self { internal })
98 }
99
100 #[inline(always)]
106 pub fn push(&mut self, value: T) -> Result<(), ArrayConstructionError> {
107 self.extend_from_array([value])
108 }
109
110 pub fn extend_from_array<const N: usize>(&mut self, values: [T; N]) -> Result<(), ArrayConstructionError> {
116 if N == 0 {
117 return Ok(());
118 }
119
120 if N > MAX_LENGTH {
121 return Err(ArrayConstructionError::ArrayTooLong);
122 }
123
124 let internal = &mut self.internal;
125 let internal_len = internal.len().value() as usize;
126 let internal_capacity = internal.capacity().value() as usize;
127 if internal_len + N > internal_capacity {
128 let missing = internal_len + N - internal_capacity;
129 let new_capacity = Self::grow_formula(internal_capacity + missing);
130 internal.grow(new_capacity)?;
131 }
132
133 let heap_data = internal.heap_data_mut();
134 let data_ptr = heap_data.data().as_ptr();
135 unsafe {
136 let end_ptr = data_ptr.add(internal_len);
137 end_ptr.copy_from_nonoverlapping(values.as_ptr(), N);
138 }
139 core::mem::forget(values);
140 *internal.len_mut() += N as i32;
141 Ok(())
142 }
143
144 #[inline(always)]
145 pub const fn len(&self) -> Length {
146 self.internal.len()
147 }
148
149 #[inline(always)]
150 pub const fn capacity(&self) -> Length {
151 self.internal.capacity()
152 }
153}
154
155impl<T: Sized, TAllocator: Allocator> Drop for ImmutableArrayBuilder<T, TAllocator> {
156 fn drop(&mut self) {
157 let internal = unsafe { core::ptr::read(&self.internal) };
160 let _ = ImmutableWeakArray::from(internal);
161 }
162}
163
164impl<T: Sized + Clone, TAllocator: Allocator> ImmutableArrayBuilder<T, TAllocator> {
165 #[inline(always)]
175 pub fn extend_from_slice(&mut self, slice: &[T]) -> Result<(), ArrayConstructionError> {
176 let slice_len = slice.len();
177 if slice_len == 0 {
178 return Ok(());
179 }
180
181 if slice_len > MAX_LENGTH {
182 return Err(ArrayConstructionError::ArrayTooLong);
183 }
184
185 let internal = &mut self.internal;
186 let internal_len = internal.len().value() as usize;
187 let internal_capacity = internal.capacity().value() as usize;
188 if internal_len + slice_len > internal_capacity {
189 let missing = internal_len + slice_len - internal_capacity;
190 let new_capacity = Self::grow_formula(internal_capacity + missing);
191 internal.grow(new_capacity)?;
192 }
193
194 let heap_data = internal.heap_data_mut();
195 let data_ptr = heap_data.data().as_ptr();
196 unsafe {
197 let mut end_ptr = data_ptr.add(internal_len);
198 for item in slice {
199 end_ptr.write(item.clone());
200 end_ptr = end_ptr.add(1);
201 }
202 }
203 *internal.len_mut() += slice_len as i32;
204 Ok(())
205 }
206}