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