#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![warn(missing_docs)]
use core::num::NonZeroUsize;
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
pub mod error;
pub mod iter;
pub mod slice;
pub mod traits;
#[cfg(feature = "alloc")]
pub mod vec;
use traits::*;
use core::fmt;
macro_rules! impl_collection {
($($ty:ty),*) => {
$(
impl<T> crate::Collection for $ty {
type Item = T;
}
impl<T> crate::Len for $ty {
fn len(&self) -> usize {
<$ty>::len(self)
}
}
)*
}
}
use impl_collection;
macro_rules! delegate_first_shared_and_co {
(<T$(: $bound:path)? $(, const $const:ident)?> $ty:ty) => {
impl<$(const $const: usize,)? T$(: $bound)?> crate::First for $ty {
fn first(&self) -> Option<&Self::Item> {
self.iter().next()
}
}
impl<$(const $const: usize,)? T$(: $bound)?> crate::Last for $ty {
fn last(&self) -> Option<&Self::Item> {
self.iter().next_back()
}
}
}
}
use delegate_first_shared_and_co;
macro_rules! delegate_first_and_co {
(<T$(: $bound:path)? $(, const $const:ident)?> $ty:ty) => {
crate::delegate_first_shared_and_co!(<T$(: $bound)? $(, const $const)?> $ty);
impl<$(const $const: usize,)? T$(: $bound)?> crate::FirstMut for $ty {
fn first_mut(&mut self) -> Option<&mut Self::Item> {
self.iter_mut().next()
}
}
impl<$(const $const: usize,)? T$(: $bound)?> crate::LastMut for $ty {
fn last_mut(&mut self) -> Option<&mut Self::Item> {
self.iter_mut().next_back()
}
}
}
}
use delegate_first_and_co;
#[cfg(feature = "alloc")]
mod alloc_impls;
#[cfg(feature = "std")]
mod std_impls;
pub use non_empty::NonEmpty;
mod non_empty {
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct NonEmpty<T: ?Sized>(T);
impl<T> NonEmpty<T> {
pub(crate) const unsafe fn new_unchecked(collection: T) -> Self {
Self(collection)
}
pub fn into_inner(self) -> T {
self.0
}
}
impl<T: ?Sized> NonEmpty<T> {
pub(crate) const fn as_inner(&self) -> &T {
&self.0
}
pub(crate) unsafe fn inner_mut(&mut self) -> &mut T {
&mut self.0
}
}
}
impl<T: fmt::Debug> fmt::Debug for NonEmpty<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self.as_inner(), f)
}
}
impl<T: fmt::Display> fmt::Display for NonEmpty<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self.as_inner(), f)
}
}
impl<T: fmt::LowerHex> fmt::LowerHex for NonEmpty<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::LowerHex::fmt(self.as_inner(), f)
}
}
impl<T: fmt::UpperHex> fmt::UpperHex for NonEmpty<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::UpperHex::fmt(self.as_inner(), f)
}
}
impl<T: fmt::Binary> fmt::Binary for NonEmpty<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Binary::fmt(self.as_inner(), f)
}
}
impl<T: fmt::Octal> fmt::Octal for NonEmpty<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Octal::fmt(self.as_inner(), f)
}
}
impl<T: fmt::Pointer> fmt::Pointer for NonEmpty<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(self.as_inner(), f)
}
}
impl<T: ?Sized> NonEmpty<T> {
pub(crate) fn as_inner_mut(&mut self) -> &mut T where T: traits::FixedLenCollection {
unsafe { self.inner_mut() }
}
pub fn iter<'a>(&'a self) -> <&'a T as IntoIterator>::IntoIter where &'a T: IntoIterator {
self.as_inner().into_iter()
}
pub fn iter_mut<'a>(&'a mut self) -> <&'a mut T as IntoIterator>::IntoIter where &'a mut T: IntoIterator {
unsafe {
self.inner_mut().into_iter()
}
}
}
impl<const N: usize, T> NonEmpty<[T; N]> {
pub const fn from_array(array: [T; N]) -> Self {
let () = IsNonZero::<N>::CHECK;
unsafe { Self::new_unchecked(array) }
}
pub const fn from_array_ref(array: &[T; N]) -> &Self {
let () = IsNonZero::<N>::CHECK;
unsafe { &*(array as *const [T; N] as *const NonEmpty<[T; N]>) }
}
pub fn from_array_mut(array: &mut [T; N]) -> &mut Self {
let () = IsNonZero::<N>::CHECK;
unsafe { &mut *(array as *mut [T; N] as *mut NonEmpty<[T; N]>) }
}
#[cfg(feature = "alloc")]
pub fn from_boxed_array(array: alloc::boxed::Box<[T; N]>) -> alloc::boxed::Box<Self> {
use alloc::boxed::Box;
let () = IsNonZero::<N>::CHECK;
unsafe { Box::from_raw(Box::into_raw(array) as *mut NonEmpty<[T; N]>) }
}
}
impl<T> NonEmpty<T> {
pub fn new(collection: T) -> Option<Self> where T: Len {
if collection.len() != 0 {
Some(unsafe { Self::new_unchecked(collection) })
} else {
None
}
}
pub fn with_first_element<I>(element: I) -> Self where T: Default + Extend<I> {
let mut this = T::default();
this.extend(core::iter::once(element));
unsafe { Self::new_unchecked(this) }
}
#[track_caller]
#[cfg(feature = "alloc")]
pub fn with_first_element_and_extra_capacity<I>(element: I, additional_capacity: usize) -> Self where T: Default + Extend<I> + Reserve {
let mut this = T::default();
this.reserve(additional_capacity + 1);
this.extend(core::iter::once(element));
unsafe { Self::new_unchecked(this) }
}
#[cfg(feature = "alloc")]
pub fn reserve(&mut self, additional: usize) where T: Reserve {
unsafe { self.inner_mut().reserve(additional) }
}
pub fn into_last_and_remaining(self) -> (T::Item, T::IntoIter) where T: IntoIterator, T::IntoIter: DoubleEndedIterator {
let mut iter = self.into_inner().into_iter();
let first = unsafe { unwrap_opt::<T, _>(iter.next_back()) };
(first, iter)
}
pub fn pop_first(self) -> (T::Item, T) where T: PopFirst + Len {
let mut inner = self.into_inner();
let first = unsafe { unwrap_opt::<T, _>(inner.pop_first()) };
(first, inner)
}
pub fn pop_last(self) -> (T::Item, T) where T: PopLast + Len {
let mut inner = self.into_inner();
let last = unsafe { unwrap_opt::<T, _>(inner.pop_last()) };
(last, inner)
}
}
impl<T: ?Sized> NonEmpty<T> {
pub fn new_ref(collection: &T) -> Option<&Self> where T: Len + SliceOrSized {
if collection.len() != 0 {
Some(unsafe { Self::new_ref_unchecked(collection) })
} else {
None
}
}
pub unsafe fn new_ref_unchecked(collection: &T) -> &Self {
&*(collection as *const T as *const NonEmpty<T>)
}
pub fn new_mut(collection: &mut T) -> Option<&mut Self> where T: Len + SliceOrSized {
if collection.len() != 0 {
Some(unsafe { Self::new_mut_unchecked(collection) })
} else {
None
}
}
pub unsafe fn new_mut_unchecked(collection: &mut T) -> &mut Self {
unsafe { &mut *(collection as *mut T as *mut NonEmpty<T>) }
}
pub fn len(&self) -> NonZeroUsize where T: Len {
unsafe { unwrap_opt::<T, _>(NonZeroUsize::new(self.as_inner().len())) }
}
pub fn first(&self) -> &T::Item where T: First {
unsafe { unwrap_opt::<T, _>(self.as_inner().first()) }
}
pub fn first_mut(&mut self) -> &mut T::Item where T: FirstMut {
unsafe { unwrap_opt::<T, _>(self.inner_mut().first_mut()) }
}
pub fn last(&self) -> &T::Item where T: Last {
unsafe { unwrap_opt::<T, _>(self.as_inner().last()) }
}
pub fn last_mut(&mut self) -> &mut T::Item where T: LastMut {
unsafe { unwrap_opt::<T, _>(self.inner_mut().last_mut()) }
}
pub fn try_pop_first(&mut self) -> Option<T::Item> where T: PopFirst + Len {
if self.as_inner().len() >= 2 {
unsafe { self.inner_mut().pop_first() }
} else {
None
}
}
pub fn try_pop_last(&mut self) -> Option<T::Item> where T: PopLast + Len {
if self.as_inner().len() >= 2 {
unsafe { self.inner_mut().pop_last() }
} else {
None
}
}
pub fn first_char(&self) -> char where T: AsRef<str> + Collection<Item=char> {
unsafe { unwrap_opt::<T, _>(self.as_inner().as_ref().chars().next()) }
}
pub fn last_char(&self) -> char where T: AsRef<str> + Collection<Item=char> {
unsafe { unwrap_opt::<T, _>(self.as_inner().as_ref().chars().next_back()) }
}
}
impl<T> NonEmpty<[T]> {
pub fn split_first(&self) -> (&T, &[T]) {
unsafe { unwrap_opt::<[T], _>(self.as_inner().split_first()) }
}
pub fn split_first_mut(&mut self) -> (&mut T, &mut [T]) {
unsafe { unwrap_opt::<[T], _>(self.inner_mut().split_first_mut()) }
}
pub fn split_last(&self) -> (&T, &[T]) {
unsafe { unwrap_opt::<[T], _>(self.as_inner().split_last()) }
}
pub fn split_last_mut(&mut self) -> (&mut T, &mut [T]) {
unsafe { unwrap_opt::<[T], _>(self.inner_mut().split_last_mut()) }
}
}
impl<T: core::ops::Deref> core::ops::Deref for NonEmpty<T> where T::Target: SliceOrSized {
type Target = NonEmpty<T::Target>;
fn deref(&self) -> &Self::Target {
unsafe { NonEmpty::new_ref_unchecked(self.as_inner()) }
}
}
impl<T: core::ops::DerefMut> core::ops::DerefMut for NonEmpty<T> where T::Target: SliceOrSized {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { NonEmpty::new_mut_unchecked(self.inner_mut()) }
}
}
impl<T: ?Sized> AsRef<T> for NonEmpty<T> {
fn as_ref(&self) -> &T {
self.as_inner()
}
}
impl<const N: usize, T> AsRef<NonEmpty<[T]>> for [T; N] {
fn as_ref(&self) -> &NonEmpty<[T]> {
NonEmpty::from_array_ref(self)
}
}
impl<const N: usize, T> AsMut<NonEmpty<[T]>> for [T; N] {
fn as_mut(&mut self) -> &mut NonEmpty<[T]> {
NonEmpty::from_array_mut(self)
}
}
impl<const N: usize, T> core::borrow::Borrow<NonEmpty<[T]>> for [T; N] {
fn borrow(&self) -> &NonEmpty<[T]> {
NonEmpty::from_array_ref(self)
}
}
impl<const N: usize, T> core::borrow::BorrowMut<NonEmpty<[T]>> for [T; N] {
fn borrow_mut(&mut self) -> &mut NonEmpty<[T]> {
NonEmpty::from_array_mut(self)
}
}
impl<T: traits::FixedLenCollection + ?Sized> AsMut<T> for NonEmpty<T> {
fn as_mut(&mut self) -> &mut T {
self.as_inner_mut()
}
}
impl<T: ?Sized> core::borrow::Borrow<T> for NonEmpty<T> {
fn borrow(&self) -> &T {
self.as_inner()
}
}
impl<T: traits::FixedLenCollection + ?Sized> core::borrow::BorrowMut<T> for NonEmpty<T> {
fn borrow_mut(&mut self) -> &mut T {
self.as_inner_mut()
}
}
impl<T: PartialEq> PartialEq<T> for NonEmpty<T> {
fn eq(&self, other: &T) -> bool {
self.as_inner() == other
}
}
impl<T: PartialOrd> PartialOrd<T> for NonEmpty<T> {
fn partial_cmp(&self, other: &T) -> Option<core::cmp::Ordering> {
self.as_inner().partial_cmp(other)
}
}
#[cfg(feature = "alloc")]
impl<T> alloc::borrow::ToOwned for NonEmpty<[T]> where T: Clone {
type Owned = vec::NonEmptyVec<T>;
fn to_owned(&self) -> Self::Owned {
unsafe {
vec::NonEmptyVec::from_vec_unchecked(self.as_inner().to_vec())
}
}
}
impl<T> traits::FromInner for NonEmpty<T> {
type Inner = T;
#[inline]
unsafe fn from_inner(inner: Self::Inner) -> Self {
Self::new_unchecked(inner)
}
}
impl<T, Item> iter::FromNonEmptyIterator<Item> for NonEmpty<T> where T: FromIterator<Item> {
fn from_non_empty_iter<I: iter::NonEmptyIntoIter<Item = Item>>(iter: I) -> Self {
iter::from_iter_spec(iter)
}
}
impl<T> IntoIterator for NonEmpty<T> where T: IntoIterator {
type Item = T::Item;
type IntoIter = T::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.into_inner().into_iter()
}
}
impl<T> iter::NonEmptyIntoIter for NonEmpty<T> where T: IntoIterator {
fn into_first_and_remaining(self) -> (Self::Item, Self::IntoIter) {
unsafe { iter::into_first_and_remaining(self) }
}
}
impl<'a, T> IntoIterator for &'a NonEmpty<T> where &'a T: IntoIterator {
type Item = <&'a T as IntoIterator>::Item;
type IntoIter = <&'a T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.as_inner().into_iter()
}
}
macro_rules! impl_refs {
(impl<T $(: $bound:path)?> $trait:ident for SmartPtr<T> $($body:tt)+) => {
impl<T $(: $bound)?> $trait for &T $($body)+
#[cfg(feature = "alloc")]
impl<T $(: $bound)?> $trait for alloc::rc::Rc<T> $($body)+
#[cfg(feature = "alloc")]
#[cfg(target_has_atomic = "ptr")]
impl<T $(: $bound)?> $trait for alloc::sync::Arc<T> $($body)+
impl_mut_refs! {
impl<T $(: $bound)?> $trait for SmartPtr<T> $($body)+
}
}
}
macro_rules! impl_mut_refs {
(impl<T $(: $bound:path)?> $trait:ident for SmartPtr<T> $($body:tt)+) => {
impl<T $(: $bound)?> $trait for &mut T $($body)+
#[cfg(feature = "alloc")]
impl<T $(: $bound)?> $trait for alloc::boxed::Box<T> $($body)+
}
}
impl_refs! {
impl<T: Len> Len for SmartPtr<T> {
fn len(&self) -> usize {
(**self).len()
}
}
}
impl<const N: usize, T> Collection for [T; N] {
type Item = T;
}
impl_collection!([T]);
impl_refs! {
impl<T: Collection> Collection for SmartPtr<T> {
type Item = T::Item;
}
}
impl_refs! {
impl<T: First> First for SmartPtr<T> {
fn first(&self) -> Option<&Self::Item> {
(**self).first()
}
}
}
impl_mut_refs! {
impl<T: FirstMut> FirstMut for SmartPtr<T> {
fn first_mut(&mut self) -> Option<&mut Self::Item> {
(**self).first_mut()
}
}
}
impl_refs! {
impl<T: Last> Last for SmartPtr<T> {
fn last(&self) -> Option<&Self::Item> {
(**self).last()
}
}
}
impl_mut_refs! {
impl<T: LastMut> LastMut for SmartPtr<T> {
fn last_mut(&mut self) -> Option<&mut Self::Item> {
(**self).last_mut()
}
}
}
delegate_first_and_co!(<T, const N> [T; N]);
delegate_first_and_co!(<T> [T]);
impl_mut_refs! {
impl<T: PopLast> PopLast for SmartPtr<T> {
fn pop_last(&mut self) -> Option<Self::Item> {
(**self).pop_last()
}
}
}
impl_mut_refs! {
impl<T: PopFirst> PopFirst for SmartPtr<T> {
fn pop_first(&mut self) -> Option<Self::Item> {
(**self).pop_first()
}
}
}
impl<T: core::str::FromStr + Len> core::str::FromStr for NonEmpty<T> {
type Err = error::CollectionError<T::Err>;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let value = s.parse::<T>().map_err(error::CollectionError::Other)?;
NonEmpty::new(value).ok_or(error::CollectionError::Empty)
}
}
#[cfg(feature = "serde")]
impl<T: serde::Serialize> serde::Serialize for NonEmpty<T> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.as_inner().serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, T: serde::Deserialize<'de> + Len> serde::Deserialize<'de> for NonEmpty<T> {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::Error;
let collection = T::deserialize(deserializer)?;
NonEmpty::new(collection).ok_or_else(|| D::Error::invalid_length(0, &"length greater than zero"))
}
}
#[cfg(feature = "parse_arg")]
impl<T: parse_arg::ParseArg + Len> parse_arg::ParseArg for NonEmpty<T> {
type Error = error::CollectionError<T::Error>;
fn describe_type<W: fmt::Write>(mut writer: W) -> fmt::Result {
T::describe_type(&mut writer)?;
write!(writer, ", which is not empty")
}
fn parse_arg(arg: &std::ffi::OsStr) -> Result<Self, Self::Error> {
let arg = T::parse_arg(arg).map_err(error::CollectionError::Other)?;
NonEmpty::new(arg).ok_or(error::CollectionError::Empty)
}
fn parse_owned_arg(arg: std::ffi::OsString) -> Result<Self, Self::Error> {
let arg = T::parse_owned_arg(arg).map_err(error::CollectionError::Other)?;
NonEmpty::new(arg).ok_or(error::CollectionError::Empty)
}
}
#[cfg_attr(not(non_empty_no_paranoid_checks), allow(unused))]
unsafe trait WellBehavedCollection {}
unsafe impl<const N: usize, T> WellBehavedCollection for [T; N] {}
unsafe impl<T> WellBehavedCollection for [T] {}
unsafe impl<T: WellBehavedCollection> WellBehavedCollection for NonEmpty<T> {}
unsafe fn unwrap_opt<Collection: ?Sized, T>(value: Option<T>) -> T {
#[cfg(not(non_empty_no_paranoid_checks))]
{
value.unwrap()
}
#[cfg(non_empty_no_paranoid_checks)]
{
if is_well_behaved::<Collection>() {
value.unwrap_unchecked()
} else {
value.unwrap()
}
}
}
fn is_well_behaved<T>() -> bool {
use core::cell::Cell;
use core::marker::PhantomData;
struct MaybeCopy<'a, U: ?Sized>(&'a Cell<bool>, PhantomData<U>);
impl<'a, U: ?Sized> Clone for MaybeCopy<'a, U> {
fn clone(&self) -> Self {
self.0.set(false);
MaybeCopy(self.0, self.1)
}
}
impl<'a, U: WellBehavedCollection + ?Sized> Copy for MaybeCopy<'a, U> {}
let is_well_behaved = Cell::new(true);
let array = [MaybeCopy(&is_well_behaved, PhantomData::<T>)];
let _ = array.clone();
is_well_behaved.get()
}
struct IsNonZero<const N: usize>;
impl<const N: usize> IsNonZero<N> {
const CHECK: () = { assert!(N != 0) };
}
#[cfg(test)]
mod tests {
}