unchecked_std/
lib.rs

1//! Rust standard library methods with some checks removed
2//! for the sake of performance and binary size.
3
4#![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
13/// A trait for `push` without the capacity check.
14pub trait PushUnchecked<T> {
15    /// Appends an element to the back of a collection without the capacity check.
16    ///
17    /// # Safety
18    ///
19    /// The capacity of the collection must be sufficient for the new item.
20    unsafe fn push_unchecked(&mut self, value: T);
21}
22
23impl<T> PushUnchecked<T> for Vec<T> {
24    /// [`Self::push`] without the capacity check.
25    ///
26    /// # Safety
27    ///
28    /// `self.len()` must be `< self.capacity()`.
29    #[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    /// `push` without the capacity check.
43    ///
44    /// # Safety
45    ///
46    /// `self.len() + ch.len_utf8()` must be `<= self.capacity()`.
47    #[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
78/// A trait for `extend` without the capacity check.
79pub trait ExtendUnchecked<T> {
80    /// Extends a collection with the contents of an iterator without the
81    /// capacity check.
82    ///
83    /// # Safety
84    ///
85    /// The capacity of the collection must be sufficient for the new items.
86    unsafe fn extend_unchecked<I: IntoIterator<Item = T>>(&mut self, iter: I);
87}
88
89impl<S: GenericString> ExtendUnchecked<char> for S {
90    /// [`Extend::extend`] without the capacity check.
91    ///
92    /// # Safety
93    ///
94    /// `self.len() + iter.into_iter().count()` must be `<= self.capacity()`.
95    #[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    /// [`Extend::extend`] without the capacity check.
105    ///
106    /// # Safety
107    ///
108    /// `self.len() + iter.into_iter().count()` must be `<= self.capacity()`.
109    #[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
117/// A trait for `extend_from_slice` without the capacity check.
118pub trait ExtendFromSliceUnchecked<T> {
119    /// Clones and appends all elements in a slice to the collection.
120    ///
121    /// # Safety
122    ///
123    /// The capacity of the collection must be sufficient for the new items.
124    unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]);
125}
126
127impl<T: Clone> ExtendFromSliceUnchecked<T> for Vec<T> {
128    /// [`Self::extend_from_slice`] without the capacity check.
129    ///
130    /// # Safety
131    ///
132    /// `other.len()` must be `<= self.capacity() - self.len()`.
133    #[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    /// [`Self::extend_from_slice`] without the capacity check.
146    ///
147    /// # Safety
148    ///
149    /// `other.len()` must be `<= self.capacity() - self.len()`.
150    #[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
160/// A trait for `extend_from_within` without the capacity and bounds checks.
161pub trait ExtendFromWithinUnchecked {
162    /// Copies elements from `src` range to the end of the collection
163    /// without the capacity check and the bounds check for the range.
164    ///
165    /// # Safety
166    ///
167    /// `src` must be a valid index for the collection.
168    /// The capacity of the collection must be sufficient for the new items.
169    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    /// `extend_from_within` without the capacity check
176    /// and the bounds check for the range.
177    ///
178    /// # Safety
179    ///
180    /// - `src` must be a valid index for `self`
181    /// - capacity of `self` must be sufficient for the new items
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        // NOTE: miri accepts this memcpy with Vec, but not with heapless::Vec,
208        // unless -Zmiri-tree-borrows is used
209        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
218/// A trait for `push_str` without the capacity check.
219pub trait PushStrUnchecked {
220    /// Appends a given string slice onto the end of this collection without
221    /// the capacity check.
222    ///
223    /// # Safety
224    ///
225    /// The capacity of the collection must be sufficient for the appended string.
226    unsafe fn push_str_unchecked(&mut self, string: &str);
227}
228
229impl<S: GenericString> PushStrUnchecked for S {
230    /// `push_str` without the capacity check.
231    ///
232    /// # Safety
233    ///
234    /// `self.len() + string.len()` must be `<= self.capacity()`.
235    #[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
242/// A trait for `copy_from_slice` without the length check.
243pub trait CopyFromSliceUnchecked<T> {
244    /// Copies all elements from `src` into `self` without the length check.
245    ///
246    /// # Safety
247    ///
248    /// The length of `self` must be equal to the length of `src`.
249    unsafe fn copy_from_slice_unchecked(&mut self, src: &[T]);
250}
251
252impl<T: Copy> CopyFromSliceUnchecked<T> for [T] {
253    /// [`Self::copy_from_slice`] without the length check.
254    ///
255    /// # Safety
256    ///
257    /// `self.len()` must be `== src.len()`.
258    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
266/// Duplicate exports in `prelude` to comply with `clippy::wildcard_imports`.
267pub mod prelude {
268    pub use super::*;
269}