Skip to main content

osom_lib_arc/carc_array/
carc_array_builder.rs

1use core::sync::atomic::Ordering;
2
3use osom_lib_alloc::traits::Allocator;
4use osom_lib_primitives::length::Length;
5use osom_lib_reprc::traits::ReprC;
6
7use crate::{
8    carc_array::{CArcArray, internal::InternalArcArray},
9    errors::CArcArrayError,
10};
11
12/// This is a builder for [`CArcArray`]. It is used to iteratively construct
13/// a [`CArcArray`], without the need of intermediate allocations.
14#[repr(transparent)]
15#[must_use]
16#[derive(Debug)]
17pub struct CArcArrayBuilder<T, TAllocator: Allocator> {
18    internal: InternalArcArray<T, TAllocator>,
19}
20
21unsafe impl<T: ReprC, TAllocator: Allocator> ReprC for CArcArrayBuilder<T, TAllocator> {
22    const CHECK: () = const {
23        osom_lib_reprc::hidden::is_reprc::<InternalArcArray<T, TAllocator>>();
24    };
25}
26
27impl<T, TAllocator: Allocator> CArcArrayBuilder<T, TAllocator> {
28    /// Creates a new [`CArcArrayBuilder`] with the default allocator.
29    ///
30    /// # Notes
31    ///
32    /// This function allocates memory.
33    ///
34    /// # Errors
35    ///
36    /// For details see [`CArcArrayError`].
37    #[inline]
38    pub fn new() -> Result<Self, CArcArrayError>
39    where
40        TAllocator: Default,
41    {
42        Self::with_capacity_and_allocator(Length::ZERO, TAllocator::default())
43    }
44
45    /// Creates a new [`CArcArrayBuilder`] with the given capacity and the default allocator.
46    ///
47    /// # Notes
48    ///
49    /// This function allocates memory.
50    ///
51    /// # Errors
52    ///
53    /// For details see [`CArcArrayError`].
54    #[inline]
55    pub fn with_capacity(capacity: Length) -> Result<Self, CArcArrayError>
56    where
57        TAllocator: Default,
58    {
59        Self::with_capacity_and_allocator(capacity, TAllocator::default())
60    }
61
62    /// Creates a new [`CArcArrayBuilder`] with the given capacity and allocator.
63    ///
64    /// # Notes
65    ///
66    /// This function allocates memory.
67    ///
68    /// # Errors
69    ///
70    /// For details see [`CArcArrayError`].
71    #[inline]
72    pub fn with_capacity_and_allocator(capacity: Length, allocator: TAllocator) -> Result<Self, CArcArrayError> {
73        let internal = InternalArcArray::new(capacity, allocator)?;
74        Ok(Self { internal })
75    }
76
77    /// Pushes a new slice to the [`CArcArrayBuilder`].
78    ///
79    /// # Notes
80    ///
81    /// This function clones the data.
82    ///
83    /// # Errors
84    ///
85    /// For details see [`CArcArrayError`].
86    #[inline]
87    pub fn try_push_slice(&mut self, slice: &[T]) -> Result<(), CArcArrayError>
88    where
89        T: Clone,
90    {
91        self.internal.try_push_slice(slice)
92    }
93
94    /// Pushes a new array to the [`CArcArrayBuilder`].
95    ///
96    /// # Notes
97    ///
98    /// This function moves the data.
99    ///
100    /// # Errors
101    ///
102    /// For details see [`CArcArrayError`].
103    #[inline]
104    pub fn try_push_array<const N: usize>(&mut self, array: [T; N]) -> Result<(), CArcArrayError> {
105        self.internal.try_push_array(array)
106    }
107
108    /// Shrinks the underlying buffer to match the length of the buffer exactly.
109    ///
110    /// # Notes
111    ///
112    /// This function may reallocate the underlying buffer, depending on the
113    /// allocator's behavior.
114    ///
115    /// # Errors
116    ///
117    /// For details see [`CArcArrayError`].
118    #[inline]
119    pub fn shrink_to_fit(&mut self) -> Result<(), CArcArrayError> {
120        self.internal.shrink_to_fit()
121    }
122
123    /// Builds a new [`CArcArray`] out of the [`CArcArrayBuilder`].
124    #[inline]
125    pub fn build(self) -> CArcArray<T, TAllocator> {
126        let internal = unsafe { core::ptr::read(&raw const self.internal) };
127        core::mem::forget(self);
128        internal.strong().store(1, Ordering::Relaxed);
129        internal.weak().store(1, Ordering::Relaxed);
130        CArcArray::from_internal(internal)
131    }
132}
133
134impl<T, TAllocator: Allocator> Drop for CArcArrayBuilder<T, TAllocator> {
135    fn drop(&mut self) {
136        if core::mem::needs_drop::<T>() {
137            for item in self.internal.data_slice_mut() {
138                unsafe { core::ptr::drop_in_place(item) };
139            }
140        }
141        unsafe { self.internal.deallocate_memory() };
142    }
143}