1#![cfg_attr(not(feature = "std"), no_std)]
4
5#[cfg(not(feature = "std"))]
6extern crate core as std;
7use std::ptr;
8
9macro_rules! idx_check (
10 ($slice:expr, $idx:expr) => {
11 assert!($idx < $slice.len(),
12 concat!("`", stringify!($idx), "` ({}) out of bounds. Length: {}"),
13 $idx, $slice.len());
14 }
15);
16
17macro_rules! len_check (
18 ($slice:expr, $start:ident, $len:ident) => {
19 assert!(
20 $start.checked_add($len)
21 .expect(concat!("Overflow evaluating ", stringify!($start + $len)))
22 <= $slice.len(),
23 "Length {} starting at {} is out of bounds (slice len {}).", $len, $start, $slice.len()
24 )
25 }
26);
27
28pub fn copy_over<T: Copy>(slice: &mut [T], src_idx: usize, dest_idx: usize, len: usize) {
37 if slice.len() == 0 { return; }
38
39 idx_check!(slice, src_idx);
40 idx_check!(slice, dest_idx);
41 len_check!(slice, src_idx, len);
42 len_check!(slice, dest_idx, len);
43
44 #[cfg(miri)]
47 slice.iter().copied().for_each(drop);
48
49 let ptr = slice.as_mut_ptr();
50
51 unsafe {
52 ptr::copy(ptr.offset(src_idx as isize), ptr.offset(dest_idx as isize), len);
53 }
54}
55
56pub fn write_bytes(slice: &mut [u8], byte: u8) {
58 unsafe {
59 ptr::write_bytes(slice.as_mut_ptr(), byte, slice.len());
60 }
61}
62
63#[cfg(feature = "std")]
69pub fn prepend<T: Copy>(elems: &[T], vec: &mut Vec<T>) {
70 let elems_len = elems.len(); if elems_len == 0 { return; }
72
73 let old_len = vec.len(); if old_len == 0 {
75 vec.extend_from_slice(elems);
77 } else {
78 vec.reserve(elems_len);
80 let ptr = vec.as_mut_ptr();
81 unsafe {
82 ptr::copy(
84 ptr,
85 ptr.offset(elems_len as isize),
86 old_len,
87 );
88 ptr::copy_nonoverlapping(
90 elems.as_ptr(),
91 ptr,
92 elems_len,
93 );
94 vec.set_len(old_len + elems_len);
96 }
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 #[should_panic]
106 fn bounds_check() {
107 let mut arr = [0i32, 1, 2, 3, 4, 5];
108
109 copy_over(&mut arr, 2, 1, 7);
110 }
111
112 #[test]
113 fn copy_empty() {
114 let mut arr: [i32; 0] = [];
115
116 copy_over(&mut arr, 0, 0, 0);
117 }
118
119 #[test]
120 #[cfg(feature = "std")]
121 fn prepend_empty() {
122 let mut vec: Vec<i32> = vec![];
123 prepend(&[1, 2, 3], &mut vec);
124 }
125
126 #[test]
127 #[cfg(feature = "std")]
128 fn prepend_i32() {
129 let mut vec = vec![3, 4, 5];
130 prepend(&[1, 2], &mut vec);
131 assert_eq!(vec, &[1, 2, 3, 4, 5]);
132 }
133
134 #[test]
136 #[cfg(all(
137 feature = "std",
138 miri,
139 ))]
140 fn prepend_bool() {
141 prepend(&[true], &mut vec![false]);
142 }
143}