1#![no_std]
4
5extern crate alloc;
6use self::{generic_string::GenericString, generic_vec::GenericVec};
7use alloc::vec::Vec;
8
9mod generic_string;
10mod generic_vec;
11
12pub trait PushUnchecked<T> {
14 unsafe fn push_unchecked(&mut self, value: T);
20}
21
22impl<T> PushUnchecked<T> for Vec<T> {
23 #[inline]
29 unsafe fn push_unchecked(&mut self, value: T) {
30 debug_assert!(self.len() < self.capacity());
31 if self.len() >= self.capacity() {
32 core::hint::unreachable_unchecked();
33 }
34
35 core::ptr::write(self.as_mut_ptr().add(self.len()), value);
36 self.set_len(self.len() + 1);
37 }
38}
39
40impl<S: GenericString> PushUnchecked<char> for S {
41 #[inline]
47 unsafe fn push_unchecked(&mut self, ch: char) {
48 let len = self.len();
49 let ch_len = ch.len_utf8();
50 debug_assert!(len + ch_len <= self.capacity());
51 let ptr = self.as_mut_vec().as_mut_ptr().add(len);
52 match ch_len {
53 1 => {
54 *ptr = ch as u8;
55 }
56 2 => {
57 *ptr = (ch as u32 >> 6 & 0x1F) as u8 | 0b1100_0000;
58 *ptr.add(1) = (ch as u32 & 0x3F) as u8 | 0b1000_0000;
59 }
60 3 => {
61 *ptr = (ch as u32 >> 12 & 0x0F) as u8 | 0b1110_0000;
62 *ptr.add(1) = (ch as u32 >> 6 & 0x3F) as u8 | 0b1000_0000;
63 *ptr.add(2) = (ch as u32 & 0x3F) as u8 | 0b1000_0000;
64 }
65 4 => {
66 *ptr = (ch as u32 >> 18 & 0x07) as u8 | 0b1111_0000;
67 *ptr.add(1) = (ch as u32 >> 12 & 0x3F) as u8 | 0b1000_0000;
68 *ptr.add(2) = (ch as u32 >> 6 & 0x3F) as u8 | 0b1000_0000;
69 *ptr.add(3) = (ch as u32 & 0x3F) as u8 | 0b1000_0000;
70 }
71 _ => core::hint::unreachable_unchecked(),
72 }
73 self.as_mut_vec().set_len(len + ch_len);
74 }
75}
76
77pub trait ExtendUnchecked<T> {
79 unsafe fn extend_unchecked<I: IntoIterator<Item = T>>(&mut self, iter: I);
86}
87
88impl<S: GenericString> ExtendUnchecked<char> for S {
89 #[inline]
95 unsafe fn extend_unchecked<I: IntoIterator<Item = char>>(&mut self, iter: I) {
96 for ch in iter {
97 self.push_unchecked(ch);
98 }
99 }
100}
101
102impl<'a, S: GenericString> ExtendUnchecked<&'a char> for S {
103 #[inline]
109 unsafe fn extend_unchecked<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
110 for &ch in iter {
111 self.push_unchecked(ch);
112 }
113 }
114}
115
116pub trait ExtendFromSliceUnchecked<T> {
118 unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]);
124}
125
126impl<T: Clone> ExtendFromSliceUnchecked<T> for Vec<T> {
127 #[inline]
133 unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]) {
134 debug_assert!(other.len() <= self.capacity() - self.len());
135 if other.len() > self.capacity() - self.len() {
136 core::hint::unreachable_unchecked();
137 }
138 self.extend_from_slice(other);
139 }
140}
141
142#[cfg(feature = "heapless")]
143impl<T: Copy, const N: usize> ExtendFromSliceUnchecked<T> for heapless::Vec<T, N> {
144 #[inline]
150 unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]) {
151 let len = self.len();
152 let count = other.len();
153 debug_assert!(count <= self.capacity() - len);
154 core::ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut_ptr().add(len), count);
155 self.set_len(len + count);
156 }
157}
158
159pub trait ExtendFromWithinUnchecked {
161 unsafe fn extend_from_within_unchecked<R>(&mut self, src: R)
169 where
170 R: core::ops::RangeBounds<usize>;
171}
172
173impl<T: Copy, V: GenericVec<Item = T>> ExtendFromWithinUnchecked for V {
174 #[inline]
182 unsafe fn extend_from_within_unchecked<R>(&mut self, src: R)
183 where
184 R: core::ops::RangeBounds<usize>,
185 {
186 let start = match src.start_bound() {
187 core::ops::Bound::Included(&start) => start,
188 core::ops::Bound::Excluded(&start) => {
189 debug_assert!(start != usize::MAX);
190 start + 1
191 }
192 core::ops::Bound::Unbounded => 0,
193 };
194 let end = match src.end_bound() {
195 core::ops::Bound::Included(&end) => {
196 debug_assert!(end != usize::MAX);
197 end + 1
198 }
199 core::ops::Bound::Excluded(&end) => end,
200 core::ops::Bound::Unbounded => self.len(),
201 };
202 debug_assert!(start <= end && end <= self.len());
203
204 let count = end - start;
205 debug_assert!(self.capacity() - self.len() >= count);
206
207 core::ptr::copy_nonoverlapping(
210 self.as_ptr().add(start),
211 self.as_mut_ptr().add(self.len()),
212 count,
213 );
214 self.set_len(self.len() + count);
215 }
216}
217
218pub trait PushStrUnchecked {
220 unsafe fn push_str_unchecked(&mut self, string: &str);
227}
228
229impl<S: GenericString> PushStrUnchecked for S {
230 #[inline]
236 unsafe fn push_str_unchecked(&mut self, string: &str) {
237 self.as_mut_vec()
238 .extend_from_slice_unchecked(string.as_bytes());
239 }
240}
241
242pub trait CopyFromSliceUnchecked<T> {
244 unsafe fn copy_from_slice_unchecked(&mut self, src: &[T]);
250}
251
252impl<T: Copy> CopyFromSliceUnchecked<T> for [T] {
253 #[inline]
259 unsafe fn copy_from_slice_unchecked(&mut self, src: &[T]) {
260 debug_assert!(self.len() == src.len());
261 unsafe {
262 core::ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
263 }
264 }
265}
266
267pub trait PushManyUnchecked<T> {
269 unsafe fn push_many_unchecked(&mut self, value: T, count: usize);
276}
277
278impl<V: GenericVec<Item = u8>> PushManyUnchecked<u8> for V {
279 #[inline]
286 unsafe fn push_many_unchecked(&mut self, byte: u8, count: usize) {
287 debug_assert!(self.capacity() - self.len() >= count);
288
289 core::ptr::write_bytes(self.as_mut_ptr().add(self.len()), byte, count);
290 self.set_len(self.len() + count);
291 }
292}
293
294impl<V: GenericVec<Item = i8>> PushManyUnchecked<i8> for V {
295 #[inline]
302 unsafe fn push_many_unchecked(&mut self, byte: i8, count: usize) {
303 debug_assert!(self.capacity() - self.len() >= count);
304
305 core::ptr::write_bytes(
306 self.as_mut_ptr().add(self.len()),
307 byte.cast_unsigned(),
308 count,
309 );
310 self.set_len(self.len() + count);
311 }
312}
313
314pub mod prelude {
316 pub use super::*;
317}