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