1#![no_std]
5
6extern crate alloc;
7use self::{generic_string::GenericString, generic_vec::GenericVec};
8use alloc::vec::Vec;
9
10mod generic_string;
11mod generic_vec;
12
13pub trait PushUnchecked<T> {
15 unsafe fn push_unchecked(&mut self, value: T);
21}
22
23impl<T> PushUnchecked<T> for Vec<T> {
24 #[inline]
30 unsafe fn push_unchecked(&mut self, value: T) {
31 debug_assert!(self.len() < self.capacity());
32 if self.len() >= self.capacity() {
33 core::hint::unreachable_unchecked();
34 }
35
36 core::ptr::write(self.as_mut_ptr().add(self.len()), value);
37 self.set_len(self.len() + 1);
38 }
39}
40
41impl<S: GenericString> PushUnchecked<char> for S {
42 #[inline]
48 unsafe fn push_unchecked(&mut self, ch: char) {
49 let len = self.len();
50 let ch_len = ch.len_utf8();
51 debug_assert!(len + ch_len <= self.capacity());
52 let ptr = self.as_mut_vec().as_mut_ptr().add(len);
53 match ch_len {
54 1 => {
55 *ptr = ch as u8;
56 }
57 2 => {
58 *ptr = (ch as u32 >> 6 & 0x1F) as u8 | 0b1100_0000;
59 *ptr.add(1) = (ch as u32 & 0x3F) as u8 | 0b1000_0000;
60 }
61 3 => {
62 *ptr = (ch as u32 >> 12 & 0x0F) as u8 | 0b1110_0000;
63 *ptr.add(1) = (ch as u32 >> 6 & 0x3F) as u8 | 0b1000_0000;
64 *ptr.add(2) = (ch as u32 & 0x3F) as u8 | 0b1000_0000;
65 }
66 4 => {
67 *ptr = (ch as u32 >> 18 & 0x07) as u8 | 0b1111_0000;
68 *ptr.add(1) = (ch as u32 >> 12 & 0x3F) as u8 | 0b1000_0000;
69 *ptr.add(2) = (ch as u32 >> 6 & 0x3F) as u8 | 0b1000_0000;
70 *ptr.add(3) = (ch as u32 & 0x3F) as u8 | 0b1000_0000;
71 }
72 _ => core::hint::unreachable_unchecked(),
73 }
74 self.as_mut_vec().set_len(len + ch_len);
75 }
76}
77
78pub trait ExtendUnchecked<T> {
80 unsafe fn extend_unchecked<I: IntoIterator<Item = T>>(&mut self, iter: I);
87}
88
89impl<S: GenericString> ExtendUnchecked<char> for S {
90 #[inline]
96 unsafe fn extend_unchecked<I: IntoIterator<Item = char>>(&mut self, iter: I) {
97 for ch in iter {
98 self.push_unchecked(ch);
99 }
100 }
101}
102
103impl<'a, S: GenericString> ExtendUnchecked<&'a char> for S {
104 #[inline]
110 unsafe fn extend_unchecked<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
111 for &ch in iter {
112 self.push_unchecked(ch);
113 }
114 }
115}
116
117pub trait ExtendFromSliceUnchecked<T> {
119 unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]);
125}
126
127impl<T: Clone> ExtendFromSliceUnchecked<T> for Vec<T> {
128 #[inline]
134 unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]) {
135 debug_assert!(other.len() <= self.capacity() - self.len());
136 if other.len() > self.capacity() - self.len() {
137 core::hint::unreachable_unchecked();
138 }
139 self.extend_from_slice(other);
140 }
141}
142
143#[cfg(feature = "heapless")]
144impl<T: Copy, const N: usize> ExtendFromSliceUnchecked<T> for heapless::Vec<T, N> {
145 #[inline]
151 unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]) {
152 let len = self.len();
153 let count = other.len();
154 debug_assert!(count <= self.capacity() - len);
155 core::ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut_ptr().add(len), count);
156 self.set_len(len + count);
157 }
158}
159
160pub trait ExtendFromWithinUnchecked {
162 unsafe fn extend_from_within_unchecked<R>(&mut self, src: R)
170 where
171 R: core::ops::RangeBounds<usize>;
172}
173
174impl<T: Copy, V: GenericVec<Item = T>> ExtendFromWithinUnchecked for V {
175 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 unsafe fn copy_from_slice_unchecked(&mut self, src: &[T]) {
259 debug_assert!(self.len() == src.len());
260 unsafe {
261 core::ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
262 }
263 }
264}
265
266pub mod prelude {
268 pub use super::*;
269}