use core::cmp::Ordering;
use core::hint::unreachable_unchecked;
use core::mem::size_of;
use core::num::NonZeroUsize;
use core::slice;
pub struct NonEmptySlice<'a, T: Sized> {
pub(crate) inner: &'a [T],
}
const _SIZE: () = {
const FOO: [(); 1] = [()];
const SIZE: usize = size_of::<NonEmptySlice<'_, &str>>();
#[cfg(target_pointer_width = "64")]
let idx = !(SIZE == 16) as usize;
#[cfg(target_pointer_width = "32")]
let idx = !(SIZE == 8) as usize;
FOO[idx]
};
const _BUILTIN_TRAITS: () = {
impl<'a, T: Clone> Clone for NonEmptySlice<'a, T> {
fn clone(&self) -> Self {
Self { inner: self.inner }
}
}
impl<'a, T: Copy> Copy for NonEmptySlice<'a, T> {}
impl<'a, T: Eq> Eq for NonEmptySlice<'a, T> {}
impl<'a, T: PartialEq> PartialEq for NonEmptySlice<'a, T> {
fn eq(&self, other: &Self) -> bool {
self.as_slice().eq(other.as_slice())
}
}
impl<'a, T: Ord> Ord for NonEmptySlice<'a, T> {
fn cmp(&self, other: &Self) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<'a, T: PartialOrd> PartialOrd for NonEmptySlice<'a, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl<'a, T> AsRef<[T]> for NonEmptySlice<'a, T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
};
impl<'a, T: Sized> NonEmptySlice<'a, T> {
pub fn from_ref(e: &'a T) -> Self {
Self {
inner: slice::from_ref(e),
}
}
pub fn from_slice(slice: &'a [T]) -> Self {
Self::from_slice_checked(slice).expect("slice shouldn't be empty")
}
pub const fn from_slice_checked(slice: &'a [T]) -> Option<Self> {
if slice.is_empty() {
return None;
}
Some(Self { inner: slice })
}
pub fn as_ptr(&self) -> *const T {
self.inner.as_ptr()
}
pub fn as_slice(&self) -> &[T] {
self.inner
}
pub const fn len(&self) -> NonZeroUsize {
unsafe { NonZeroUsize::new_unchecked(self.inner.len()) }
}
pub const fn is_empty(&self) -> bool {
false
}
pub fn first(&self) -> &T {
match self.inner {
[first, ..] => first,
[] => unsafe { unreachable_unchecked() },
}
}
pub fn last(&self) -> &T {
match self.inner {
[.., last] => last,
[] => unsafe { unreachable_unchecked() },
}
}
pub fn split_first(&self) -> (&T, &[T]) {
match self.inner {
[first, rest @ ..] => (first, rest),
[] => unsafe { unreachable_unchecked() },
}
}
pub fn split_last(&self) -> (&T, &[T]) {
match self.inner {
[rest @ .., last] => (last, rest),
[] => unsafe { unreachable_unchecked() },
}
}
}