1#[cfg(feature = "alloc")]
2#[allow(unused_imports)]
3use alloc::vec::Vec;
4
5#[allow(dead_code)] #[must_use]
8pub(crate) const fn rem_up(a: usize, b: usize) -> usize {
9 let rem = a % b;
10 if rem > 0 {
11 rem
12 } else {
13 b
14 }
15}
16
17#[allow(dead_code)] #[inline]
19fn last_idx<T: PartialEq>(x: &[T], value: &T) -> usize {
20 x.iter().rposition(|b| b != value).map_or(0, |idx| idx + 1)
21}
22
23#[allow(dead_code)] #[inline]
25#[must_use]
26pub(crate) fn trim_end_slice<'a, T: PartialEq>(slice: &'a [T], value: &T) -> &'a [T] {
27 &slice[..last_idx(slice, value)]
28}
29
30#[cfg(feature = "alloc")]
31#[inline]
32pub(crate) fn trim_end_vec<T: PartialEq>(vec: &mut Vec<T>, value: &T) {
33 vec.truncate(last_idx(vec, value));
34}
35
36#[cfg(feature = "nightly")]
38pub(crate) use core::intrinsics::{likely, unlikely};
39
40#[cfg(not(feature = "nightly"))]
41pub(crate) use core::convert::identity as likely;
42#[cfg(not(feature = "nightly"))]
43pub(crate) use core::convert::identity as unlikely;
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn test_trim() {
51 assert_eq!(trim_end_slice(&[], &0), &[] as &[i32]);
52 assert_eq!(trim_end_slice(&[0], &0), &[] as &[i32]);
53 assert_eq!(trim_end_slice(&[0, 1], &0), &[0, 1]);
54 assert_eq!(trim_end_slice(&[0, 1, 0], &0), &[0, 1]);
55 assert_eq!(trim_end_slice(&[0, 1, 0, 0], &0), &[0, 1]);
56 assert_eq!(trim_end_slice(&[0, 1, 0, 0, 0], &0), &[0, 1]);
57 assert_eq!(trim_end_slice(&[0, 1, 0, 1, 0], &0), &[0, 1, 0, 1]);
58
59 let trim_end_vec = |mut v: Vec<i32>, x: &i32| {
60 trim_end_vec(&mut v, x);
61 v
62 };
63 assert_eq!(trim_end_vec(vec![], &0), &[] as &[i32]);
64 assert_eq!(trim_end_vec(vec![0], &0), &[] as &[i32]);
65 assert_eq!(trim_end_vec(vec![0, 1], &0), &[0, 1]);
66 assert_eq!(trim_end_vec(vec![0, 1, 0], &0), &[0, 1]);
67 assert_eq!(trim_end_vec(vec![0, 1, 0, 0], &0), &[0, 1]);
68 assert_eq!(trim_end_vec(vec![0, 1, 0, 0, 0], &0), &[0, 1]);
69 assert_eq!(trim_end_vec(vec![0, 1, 0, 1, 0], &0), &[0, 1, 0, 1]);
70 }
71}