iceoryx2_bb_container/vector/
polymorphic_vec.rs

1// Copyright (c) 2025 Contributors to the Eclipse Foundation
2//
3// See the NOTICE file(s) distributed with this work for additional
4// information regarding copyright ownership.
5//
6// This program and the accompanying materials are made available under the
7// terms of the Apache Software License 2.0 which is available at
8// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
9// which is available at https://opensource.org/licenses/MIT.
10//
11// SPDX-License-Identifier: Apache-2.0 OR MIT
12
13//! Vector implementation with a polymorphic stateful allocator.
14//!
15//! # Example
16//!
17//! ```no_run
18//! # extern crate iceoryx2_loggers;
19//!
20//! use iceoryx2_bb_elementary_traits::allocator::*;
21//! use iceoryx2_bb_container::vector::*;
22//!
23//! # struct SomeAllocator {}
24//!
25//! # impl SomeAllocator {
26//! #     fn new() -> Self {
27//! #          Self {}
28//! #     }
29//! # }
30//! #
31//! # impl BaseAllocator for SomeAllocator {
32//! #     fn allocate(
33//! #         &self,
34//! #         layout: core::alloc::Layout,
35//! #     ) -> Result<core::ptr::NonNull<[u8]>, AllocationError> {
36//! #         todo!()
37//! #     }
38//! #
39//! #     unsafe fn deallocate(&self, _ptr: core::ptr::NonNull<u8>, _layout: core::alloc::Layout) {
40//! #         todo!()
41//! #     }
42//! # }
43//!
44//! # fn main() -> Result<(), Box<dyn core::error::Error>> {
45//! let allocator = SomeAllocator::new();
46//! let capacity: usize = 123;
47//! let mut my_vec =
48//!     PolymorphicVec::<usize, SomeAllocator>::new(&allocator, capacity)?;
49//!
50//! my_vec.push(456); // returns false, when capacity is exceeded
51//! # Ok(())
52//! # }
53//! ```
54
55use alloc::format;
56use core::{
57    alloc::Layout,
58    fmt::Debug,
59    mem::MaybeUninit,
60    ops::{Deref, DerefMut},
61    ptr::NonNull,
62};
63
64use iceoryx2_bb_elementary_traits::allocator::{AllocationError, BaseAllocator};
65use iceoryx2_log::fail;
66
67use crate::vector::internal;
68pub use crate::vector::Vector;
69
70/// Runtime fixed-size vector variant with a polymorphic allocator, meaning an
71/// allocator with a state can be attached to the vector instead of using a
72/// stateless allocator like the heap-allocator.
73pub struct PolymorphicVec<'a, T, Allocator: BaseAllocator> {
74    data_ptr: *mut MaybeUninit<T>,
75    len: u64,
76    capacity: u64,
77    allocator: &'a Allocator,
78}
79
80impl<T: Debug, Allocator: BaseAllocator> Debug for PolymorphicVec<'_, T, Allocator> {
81    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
82        write!(
83            f,
84            "PolymorphicVec<{}, {}> {{ capacity: {}, len: {} content: [ ",
85            core::any::type_name::<T>(),
86            core::any::type_name::<Allocator>(),
87            self.capacity,
88            self.len,
89        )?;
90
91        if !self.is_empty() {
92            write!(f, "{:?}", self[0])?;
93        }
94
95        for idx in 1..self.len() {
96            write!(f, ", {:?}", self[idx])?;
97        }
98
99        write!(f, " ] }}")
100    }
101}
102
103impl<T, Allocator: BaseAllocator> Drop for PolymorphicVec<'_, T, Allocator> {
104    fn drop(&mut self) {
105        self.clear();
106        unsafe {
107            self.allocator.deallocate(
108                NonNull::new_unchecked(self.data_ptr.cast()),
109                Layout::array::<MaybeUninit<T>>(self.capacity as _).unwrap(),
110            )
111        };
112    }
113}
114
115impl<T, Allocator: BaseAllocator> Deref for PolymorphicVec<'_, T, Allocator> {
116    type Target = [T];
117
118    fn deref(&self) -> &Self::Target {
119        self.as_slice()
120    }
121}
122
123impl<T, Allocator: BaseAllocator> DerefMut for PolymorphicVec<'_, T, Allocator> {
124    fn deref_mut(&mut self) -> &mut Self::Target {
125        self.as_mut_slice()
126    }
127}
128
129impl<T: PartialEq, Allocator: BaseAllocator> PartialEq for PolymorphicVec<'_, T, Allocator> {
130    fn eq(&self, other: &Self) -> bool {
131        if self.len != other.len {
132            return false;
133        }
134
135        for i in 0..self.len() {
136            if other[i] != self[i] {
137                return false;
138            }
139        }
140
141        true
142    }
143}
144
145impl<T: Eq, Allocator: BaseAllocator> Eq for PolymorphicVec<'_, T, Allocator> {}
146
147unsafe impl<T: Send, Allocator: BaseAllocator> Send for PolymorphicVec<'_, T, Allocator> {}
148
149impl<'a, T, Allocator: BaseAllocator> PolymorphicVec<'a, T, Allocator> {
150    /// Creates a new [`PolymorphicVec`].
151    pub fn new(allocator: &'a Allocator, capacity: usize) -> Result<Self, AllocationError> {
152        let layout = Layout::array::<MaybeUninit<T>>(capacity as _)
153            .expect("Memory size for the array is smaller than isize::MAX");
154        let mut data_ptr = match allocator.allocate(layout) {
155            Ok(ptr) => ptr,
156            Err(e) => {
157                let origin = format!(
158                    "PolymorphicVec::<{}, {}>::new(.., {})",
159                    core::any::type_name::<T>(),
160                    core::any::type_name::<Allocator>(),
161                    capacity
162                );
163                fail!(from origin, with e,
164                    "Failed to create new PolymorphicVec due to a failure while allocating memory ({e:?}).");
165            }
166        };
167
168        Ok(Self {
169            data_ptr: unsafe { data_ptr.as_mut() }.as_mut_ptr().cast(),
170            len: 0,
171            capacity: capacity as _,
172            allocator,
173        })
174    }
175
176    /// Creates a new [`PolymorphicVec`] with the provided capacity and fills it by using the provided callback
177    pub fn from_fn<F: FnMut(usize) -> T>(
178        allocator: &'a Allocator,
179        capacity: usize,
180        mut func: F,
181    ) -> Result<Self, AllocationError> {
182        let mut new_self = Self::new(allocator, capacity)?;
183
184        for n in 0..capacity {
185            unsafe { new_self.push_unchecked(func(n)) };
186        }
187
188        Ok(new_self)
189    }
190}
191
192impl<'a, T: Clone, Allocator: BaseAllocator> PolymorphicVec<'a, T, Allocator> {
193    /// Same as clone but it can fail when the required memory could not be
194    /// allocated from the [`BaseAllocator`].
195    pub fn try_clone(&self) -> Result<Self, AllocationError> {
196        let layout = Layout::array::<MaybeUninit<T>>(self.capacity as _)
197            .expect("Memory size for the array is smaller than isize::MAX");
198
199        let mut data_ptr = match self.allocator.allocate(layout) {
200            Ok(ptr) => ptr,
201            Err(e) => {
202                let origin = format!(
203                    "PolymorphicVec::<{}, {}>::try_clone()",
204                    core::any::type_name::<T>(),
205                    core::any::type_name::<Allocator>(),
206                );
207                fail!(from origin, with e,
208                    "Failed to clone PolymorphicVec due to a failure while allocating memory ({e:?}).");
209            }
210        };
211
212        let mut new_self = Self {
213            data_ptr: unsafe { data_ptr.as_mut() }.as_mut_ptr().cast(),
214            len: 0,
215            capacity: self.capacity,
216            allocator: self.allocator,
217        };
218
219        unsafe { new_self.extend_from_slice_unchecked(self.as_slice()) };
220        Ok(new_self)
221    }
222}
223
224impl<T, Allocator: BaseAllocator> internal::VectorView<T> for PolymorphicVec<'_, T, Allocator> {
225    fn data(&self) -> &[MaybeUninit<T>] {
226        unsafe { core::slice::from_raw_parts(self.data_ptr, self.capacity()) }
227    }
228
229    unsafe fn data_mut(&mut self) -> &mut [MaybeUninit<T>] {
230        unsafe { core::slice::from_raw_parts_mut(self.data_ptr, self.capacity()) }
231    }
232
233    unsafe fn set_len(&mut self, len: u64) {
234        self.len = len
235    }
236}
237
238impl<T, Allocator: BaseAllocator> Vector<T> for PolymorphicVec<'_, T, Allocator> {
239    fn capacity(&self) -> usize {
240        self.capacity as _
241    }
242
243    fn len(&self) -> usize {
244        self.len as usize
245    }
246}