iceoryx2_bb_container/string/
polymorphic_string.rs1use alloc::format;
37use core::{
38 alloc::Layout,
39 cmp::Ordering,
40 fmt::{Debug, Display},
41 hash::Hash,
42 mem::MaybeUninit,
43 ops::Deref,
44 ptr::NonNull,
45};
46
47use iceoryx2_bb_elementary_traits::{
48 allocator::{Allocate, AllocationError, Deallocate},
49 pointer::Pointer,
50};
51
52use crate::string::*;
53
54pub struct PolymorphicString<'a, Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> {
58 data_ptr: *mut MaybeUninit<u8>,
59 len: u64,
60 capacity: u64,
61 allocator: &'a Allocator,
62}
63
64impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> Drop
65 for PolymorphicString<'_, Allocator>
66{
67 fn drop(&mut self) {
68 unsafe {
69 self.allocator.deallocate(
70 NonNull::new_unchecked(self.data_ptr.cast()),
71 Layout::array::<MaybeUninit<u8>>(self.capacity as usize + 1)
72 .expect("Memory size for the array is smaller than isize::MAX"),
73 )
74 };
75 }
76}
77
78impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> internal::StringView
79 for PolymorphicString<'_, Allocator>
80{
81 fn data(&self) -> &[MaybeUninit<u8>] {
82 unsafe { core::slice::from_raw_parts(self.data_ptr, self.capacity() + 1) }
83 }
84
85 unsafe fn data_mut(&mut self) -> &mut [MaybeUninit<u8>] {
86 unsafe { core::slice::from_raw_parts_mut(self.data_ptr, self.capacity() + 1) }
87 }
88
89 unsafe fn set_len(&mut self, len: u64) {
90 self.len = len;
91 }
92}
93
94impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> Debug
95 for PolymorphicString<'_, Allocator>
96{
97 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
98 write!(
99 f,
100 "PolymorphicString::<{}> {{ capacity: {}, len: {}, data: \"{}\" }}",
101 core::any::type_name::<Allocator>(),
102 self.capacity,
103 self.len,
104 as_escaped_string(self.as_bytes())
105 )
106 }
107}
108
109unsafe impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> Send
110 for PolymorphicString<'_, Allocator>
111{
112}
113
114impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>>
115 PartialOrd<PolymorphicString<'_, Allocator>> for PolymorphicString<'_, Allocator>
116{
117 fn partial_cmp(&self, other: &PolymorphicString<'_, Allocator>) -> Option<Ordering> {
118 Some(self.cmp(other))
119 }
120}
121
122impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> Ord
123 for PolymorphicString<'_, Allocator>
124{
125 fn cmp(&self, other: &Self) -> Ordering {
126 self.as_bytes().cmp(other.as_bytes())
127 }
128}
129
130impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> Hash
131 for PolymorphicString<'_, Allocator>
132{
133 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
134 state.write(self.as_bytes())
135 }
136}
137
138impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> Deref
139 for PolymorphicString<'_, Allocator>
140{
141 type Target = [u8];
142
143 fn deref(&self) -> &Self::Target {
144 self.as_bytes()
145 }
146}
147
148impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>>
149 PartialEq<PolymorphicString<'_, Allocator>> for PolymorphicString<'_, Allocator>
150{
151 fn eq(&self, other: &PolymorphicString<'_, Allocator>) -> bool {
152 *self.as_bytes() == *other.as_bytes()
153 }
154}
155
156impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> Eq
157 for PolymorphicString<'_, Allocator>
158{
159}
160
161impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> PartialEq<&[u8]>
162 for PolymorphicString<'_, Allocator>
163{
164 fn eq(&self, other: &&[u8]) -> bool {
165 *self.as_bytes() == **other
166 }
167}
168
169impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> PartialEq<&str>
170 for PolymorphicString<'_, Allocator>
171{
172 fn eq(&self, other: &&str) -> bool {
173 *self.as_bytes() == *other.as_bytes()
174 }
175}
176
177impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>>
178 PartialEq<PolymorphicString<'_, Allocator>> for &str
179{
180 fn eq(&self, other: &PolymorphicString<'_, Allocator>) -> bool {
181 *self.as_bytes() == *other.as_bytes()
182 }
183}
184
185impl<const OTHER_CAPACITY: usize, Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>>
186 PartialEq<[u8; OTHER_CAPACITY]> for PolymorphicString<'_, Allocator>
187{
188 fn eq(&self, other: &[u8; OTHER_CAPACITY]) -> bool {
189 *self.as_bytes() == *other
190 }
191}
192
193impl<const OTHER_CAPACITY: usize, Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>>
194 PartialEq<&[u8; OTHER_CAPACITY]> for PolymorphicString<'_, Allocator>
195{
196 fn eq(&self, other: &&[u8; OTHER_CAPACITY]) -> bool {
197 *self.as_bytes() == **other
198 }
199}
200
201impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> Display
202 for PolymorphicString<'_, Allocator>
203{
204 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
205 write!(f, "{}", as_escaped_string(self.as_bytes()))
206 }
207}
208
209impl<'a, Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>>
210 PolymorphicString<'a, Allocator>
211{
212 pub fn new(allocator: &'a Allocator, capacity: usize) -> Result<Self, AllocationError> {
214 let layout = Layout::array::<MaybeUninit<u8>>(capacity + 1)
215 .expect("Memory size for the array is smaller than isize::MAX");
216 let mut data_ptr = match allocator.allocate(layout) {
217 Ok(ptr) => ptr,
218 Err(e) => {
219 let origin = format!(
220 "PolymorphicString::<{}>::new(.., {})",
221 core::any::type_name::<Allocator>(),
222 capacity
223 );
224 fail!(from origin, with e,
225 "Failed to create new PolymorphicString due to a failure while allocating memory ({e:?}).");
226 }
227 };
228
229 unsafe { *data_ptr.as_mut_ptr() = 0 };
231
232 Ok(Self {
233 data_ptr: data_ptr.as_mut_ptr().cast(),
234 len: 0,
235 capacity: capacity as _,
236 allocator,
237 })
238 }
239
240 pub fn try_clone(&self) -> Result<Self, AllocationError> {
243 let layout = Layout::array::<MaybeUninit<u8>>(self.capacity as usize + 1)
244 .expect("Memory size for the array is smaller than isize::MAX");
245
246 let mut data_ptr = match self.allocator.allocate(layout) {
247 Ok(ptr) => ptr,
248 Err(e) => {
249 let origin = format!(
250 "PolymorphicString::<{}>::try_clone()",
251 core::any::type_name::<Allocator>(),
252 );
253 fail!(from origin, with e,
254 "Failed to clone PolymorphicString due to a failure while allocating memory ({e:?}).");
255 }
256 };
257
258 let mut new_self = Self {
259 data_ptr: data_ptr.as_mut_ptr().cast(),
260 len: 0,
261 capacity: self.capacity,
262 allocator: self.allocator,
263 };
264
265 unsafe { new_self.insert_bytes_unchecked(0, self.as_bytes()) };
266 Ok(new_self)
267 }
268}
269
270impl<Allocator: Allocate<NonNull<u8>> + Deallocate<NonNull<u8>>> String
271 for PolymorphicString<'_, Allocator>
272{
273 fn capacity(&self) -> usize {
274 self.capacity as usize
275 }
276
277 fn len(&self) -> usize {
278 self.len as usize
279 }
280}