#![no_std]
extern crate alloc;
use self::{generic_string::GenericString, generic_vec::GenericVec};
use alloc::vec::Vec;
mod generic_string;
mod generic_vec;
pub trait PushUnchecked<T> {
unsafe fn push_unchecked(&mut self, value: T);
}
impl<T> PushUnchecked<T> for Vec<T> {
#[inline]
unsafe fn push_unchecked(&mut self, value: T) {
debug_assert!(self.len() < self.capacity());
if self.len() >= self.capacity() {
core::hint::unreachable_unchecked();
}
core::ptr::write(self.as_mut_ptr().add(self.len()), value);
self.set_len(self.len() + 1);
}
}
impl<S: GenericString> PushUnchecked<char> for S {
#[inline]
unsafe fn push_unchecked(&mut self, ch: char) {
let len = self.len();
let ch_len = ch.len_utf8();
debug_assert!(len + ch_len <= self.capacity());
let ptr = self.as_mut_vec().as_mut_ptr().add(len);
match ch_len {
1 => {
*ptr = ch as u8;
}
2 => {
*ptr = (ch as u32 >> 6 & 0x1F) as u8 | 0b1100_0000;
*ptr.add(1) = (ch as u32 & 0x3F) as u8 | 0b1000_0000;
}
3 => {
*ptr = (ch as u32 >> 12 & 0x0F) as u8 | 0b1110_0000;
*ptr.add(1) = (ch as u32 >> 6 & 0x3F) as u8 | 0b1000_0000;
*ptr.add(2) = (ch as u32 & 0x3F) as u8 | 0b1000_0000;
}
4 => {
*ptr = (ch as u32 >> 18 & 0x07) as u8 | 0b1111_0000;
*ptr.add(1) = (ch as u32 >> 12 & 0x3F) as u8 | 0b1000_0000;
*ptr.add(2) = (ch as u32 >> 6 & 0x3F) as u8 | 0b1000_0000;
*ptr.add(3) = (ch as u32 & 0x3F) as u8 | 0b1000_0000;
}
_ => core::hint::unreachable_unchecked(),
}
self.as_mut_vec().set_len(len + ch_len);
}
}
pub trait ExtendUnchecked<T> {
unsafe fn extend_unchecked<I: IntoIterator<Item = T>>(&mut self, iter: I);
}
impl<S: GenericString> ExtendUnchecked<char> for S {
#[inline]
unsafe fn extend_unchecked<I: IntoIterator<Item = char>>(&mut self, iter: I) {
for ch in iter {
self.push_unchecked(ch);
}
}
}
impl<'a, S: GenericString> ExtendUnchecked<&'a char> for S {
#[inline]
unsafe fn extend_unchecked<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
for &ch in iter {
self.push_unchecked(ch);
}
}
}
pub trait ExtendFromSliceUnchecked<T> {
unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]);
}
impl<T: Clone> ExtendFromSliceUnchecked<T> for Vec<T> {
#[inline]
unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]) {
debug_assert!(other.len() <= self.capacity() - self.len());
if other.len() > self.capacity() - self.len() {
core::hint::unreachable_unchecked();
}
self.extend_from_slice(other);
}
}
#[cfg(feature = "heapless")]
impl<T: Copy, const N: usize> ExtendFromSliceUnchecked<T> for heapless::Vec<T, N> {
#[inline]
unsafe fn extend_from_slice_unchecked(&mut self, other: &[T]) {
let len = self.len();
let count = other.len();
debug_assert!(count <= self.capacity() - len);
core::ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut_ptr().add(len), count);
self.set_len(len + count);
}
}
pub trait ExtendFromWithinUnchecked {
unsafe fn extend_from_within_unchecked<R>(&mut self, src: R)
where
R: core::ops::RangeBounds<usize>;
}
impl<T: Copy, V: GenericVec<Item = T>> ExtendFromWithinUnchecked for V {
#[inline]
unsafe fn extend_from_within_unchecked<R>(&mut self, src: R)
where
R: core::ops::RangeBounds<usize>,
{
let start = match src.start_bound() {
core::ops::Bound::Included(&start) => start,
core::ops::Bound::Excluded(&start) => {
debug_assert!(start != usize::MAX);
start + 1
}
core::ops::Bound::Unbounded => 0,
};
let end = match src.end_bound() {
core::ops::Bound::Included(&end) => {
debug_assert!(end != usize::MAX);
end + 1
}
core::ops::Bound::Excluded(&end) => end,
core::ops::Bound::Unbounded => self.len(),
};
debug_assert!(start <= end && end <= self.len());
let count = end - start;
debug_assert!(self.capacity() - self.len() >= count);
core::ptr::copy_nonoverlapping(
self.as_ptr().add(start),
self.as_mut_ptr().add(self.len()),
count,
);
self.set_len(self.len() + count);
}
}
pub trait PushStrUnchecked {
unsafe fn push_str_unchecked(&mut self, string: &str);
}
impl<S: GenericString> PushStrUnchecked for S {
#[inline]
unsafe fn push_str_unchecked(&mut self, string: &str) {
self.as_mut_vec()
.extend_from_slice_unchecked(string.as_bytes());
}
}
pub trait CopyFromSliceUnchecked<T> {
unsafe fn copy_from_slice_unchecked(&mut self, src: &[T]);
}
impl<T: Copy> CopyFromSliceUnchecked<T> for [T] {
#[inline]
unsafe fn copy_from_slice_unchecked(&mut self, src: &[T]) {
debug_assert!(self.len() == src.len());
unsafe {
core::ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
}
}
}
pub trait PushManyUnchecked<T> {
unsafe fn push_many_unchecked(&mut self, value: T, count: usize);
}
impl<V: GenericVec<Item = u8>> PushManyUnchecked<u8> for V {
#[inline]
unsafe fn push_many_unchecked(&mut self, byte: u8, count: usize) {
debug_assert!(self.capacity() - self.len() >= count);
core::ptr::write_bytes(self.as_mut_ptr().add(self.len()), byte, count);
self.set_len(self.len() + count);
}
}
impl<V: GenericVec<Item = i8>> PushManyUnchecked<i8> for V {
#[inline]
unsafe fn push_many_unchecked(&mut self, byte: i8, count: usize) {
debug_assert!(self.capacity() - self.len() >= count);
core::ptr::write_bytes(
self.as_mut_ptr().add(self.len()),
byte.cast_unsigned(),
count,
);
self.set_len(self.len() + count);
}
}
pub mod prelude {
pub use super::*;
}