use core::ops::{Bound, RangeBounds};
pub(crate) fn range_covers_slice(
range: &impl RangeBounds<usize>,
slice_len: usize,
) -> (bool, bool) {
let (covers_start, oob_start) = range_covers_slice_start(range.start_bound(), slice_len);
let (covers_end, oob_end) = range_covers_slice_end(range.end_bound(), slice_len);
(covers_start && covers_end, oob_start || oob_end)
}
fn range_covers_slice_start(start_bound: Bound<&usize>, slice_len: usize) -> (bool, bool) {
match start_bound {
Bound::Included(idx) => (*idx == 0, *idx > slice_len),
Bound::Excluded(idx) => (false, *idx >= slice_len),
Bound::Unbounded => (true, false),
}
}
fn range_covers_slice_end(end_bound: Bound<&usize>, len: usize) -> (bool, bool) {
match end_bound {
Bound::Included(idx) => {
if len == 0 {
(true, true)
} else {
(*idx >= len - 1, *idx >= len)
}
}
Bound::Excluded(idx) => (*idx >= len, *idx > len),
Bound::Unbounded => (true, false),
}
}
macro_rules! impl_wrapper {
(
base_bounds_macro = $($tb:ident : $trait:ident)?,
impl <$A:ident> $ty_name:ident<$A_:ident> {
$(fn $fn_name:ident(&$($m:ident)* $(, $param:ident: $tp:ty)*) -> $rt:ty);*
}
) => (
impl<$A> $ty_name<$A>
where
$($tb : $trait,)?
{$(
#[inline]
pub fn $fn_name(self: impl_wrapper!{__PRIV_SELF &$($m)*} $(, $param: $tp)*) -> $rt {
(self.0).$fn_name($($param),*)
}
)*}
);
(__PRIV_SELF &mut self) => (&mut Self);
(__PRIV_SELF &self) => (&Self);
}
macro_rules! shared_impl {
(@IMPORTS) => (
use core::{
borrow::{Borrow, BorrowMut},
cmp::{Eq, Ord, Ordering, PartialEq},
convert::TryFrom,
fmt::{self, Debug},
hash::{Hash, Hasher},
ops::{Deref, DerefMut, Index, IndexMut, RangeBounds},
slice::SliceIndex,
};
use alloc::{vec::Vec, boxed::Box};
);
(
base_bounds_macro = $($tb:ident : $trait:ident)?,
item_ty_macro = $item_ty:ty,
$(#[$attr:meta])*
$v:vis struct $name:ident<$t:ident>($wrapped:ident<$_t:ident>);
) => (
$(#[$attr])*
$v struct $name<$t>($wrapped<$t>)
where
$($tb : $trait,)?;
impl<$t> $name<$t>
where
$($tb : $trait,)?
{
pub fn new(first: $item_ty) -> Self {
#![allow(clippy::vec_init_then_push)]
let mut inner = $wrapped::new();
inner.push(first);
$name(inner)
}
pub fn with_capacity(first: $item_ty, capacity: usize) -> Self {
let mut vec = $wrapped::with_capacity(capacity);
vec.push(first);
$name(vec)
}
pub fn from_vec_push(mut vec: Vec<$item_ty>, last: $item_ty) -> Self {
vec.push(last);
$name($wrapped::from(vec))
}
pub fn from_vec_insert(mut vec: Vec<$item_ty>, index: usize, item: $item_ty) -> Self {
vec.insert(index, item);
$name($wrapped::from(vec))
}
pub fn try_from_vec(vec: Vec<$item_ty>) -> Result<Self, Size0Error> {
if vec.is_empty() {
Err(Size0Error)
} else {
Ok($name($wrapped::from(vec)))
}
}
pub fn last(&self) -> &$item_ty {
self.0.last().unwrap()
}
pub fn last_mut(&mut self) -> &mut $item_ty {
self.0.last_mut().unwrap()
}
pub fn first(&self) -> &$item_ty {
self.0.first().unwrap()
}
pub fn first_mut(&mut self) -> &mut $item_ty {
self.0.first_mut().unwrap()
}
pub fn truncate(&mut self, len: usize) -> Result<(), Size0Error> {
if len > 0 {
self.0.truncate(len);
Ok(())
} else {
Err(Size0Error)
}
}
#[deprecated(
since = "1.8.0",
note = "try_ prefix created ambiguity use `truncate`"
)]
#[inline(always)]
pub fn try_truncate(&mut self, len: usize) -> Result<(), Size0Error> {
self.truncate(len)
}
pub fn swap_remove(&mut self, index: usize) -> Result<$item_ty, Size0Error> {
if self.len() > 1 {
Ok(self.0.swap_remove(index))
} else {
Err(Size0Error)
}
}
#[deprecated(
since = "1.8.0",
note = "try_ prefix created ambiguity use `swap_remove`"
)]
#[inline(always)]
pub fn try_swap_remove(&mut self, index: usize) -> Result<$item_ty, Size0Error> {
self.swap_remove(index)
}
pub fn remove(&mut self, index: usize) -> Result<$item_ty, Size0Error> {
if self.len() > 1 {
Ok(self.0.remove(index))
} else {
Err(Size0Error)
}
}
#[deprecated(
since = "1.8.0",
note = "try_ prefix created ambiguity use `remove`, also try_remove PANICS on out of bounds"
)]
#[inline(always)]
pub fn try_remove(&mut self, index: usize) -> Result<$item_ty, Size0Error> {
self.remove(index)
}
pub fn drain<R>(&mut self, range: R) -> Result<Drain<'_, $t>, Size0Error>
where
R: RangeBounds<usize>
{
let (covers_all, out_of_bounds) = crate::shared::range_covers_slice(&range, self.len());
if covers_all && !out_of_bounds {
Err(Size0Error)
} else {
Ok(self.0.drain(range))
}
}
pub fn retain<F>(&mut self, mut f: F) -> Result<(), Size0Error>
where
F: FnMut(&$item_ty) -> bool
{
let len = self.len();
let mut del = 0;
{
let v = &mut **self;
for i in 0..len {
if !f(&v[i]) {
del += 1;
} else if del > 0 {
v.swap(i - del, i);
}
}
}
if del == 0 {
Ok(())
} else {
if del < len {
self.0.truncate(len - del);
Ok(())
} else {
self.swap(0, len - 1);
self.0.truncate(1);
Err(Size0Error)
}
}
}
pub fn dedup_by_key<F, K>(&mut self, key: F)
where
F: FnMut(&mut $item_ty) -> K,
K: PartialEq<K>,
{
self.0.dedup_by_key(key)
}
pub fn dedup_by<F>(&mut self, same_bucket: F)
where
F: FnMut(&mut $item_ty, &mut $item_ty) -> bool,
{
self.0.dedup_by(same_bucket)
}
pub fn pop(&mut self) -> Result<$item_ty, Size0Error> {
if self.len() > 1 {
Ok(self.0.pop().unwrap())
} else {
Err(Size0Error)
}
}
#[deprecated(
since = "1.8.0",
note = "try_ prefix created ambiguity use `pop`"
)]
#[inline(always)]
pub fn try_pop(&mut self) -> Result<$item_ty, Size0Error> {
self.pop()
}
pub fn resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), Size0Error>
where
F: FnMut() -> $item_ty
{
if new_len > 0 {
self.0.resize_with(new_len, f);
Ok(())
} else {
Err(Size0Error)
}
}
#[deprecated(
since = "1.8.0",
note = "try_ prefix created ambiguity use `resize_with`"
)]
#[inline(always)]
pub fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), Size0Error>
where
F: FnMut() -> $item_ty
{
self.resize_with(new_len, f)
}
pub fn split_off_first(self) -> ($item_ty, $wrapped<$t>) {
let mut smallvec = self.0;
let first = smallvec.remove(0);
(first, smallvec)
}
pub fn split_off_last(self) -> ($wrapped<$t>, $item_ty) {
let mut smallvec = self.0;
let last = smallvec.remove(smallvec.len() - 1);
(smallvec, last)
}
pub fn into_boxed_slice(self) -> Box<[$item_ty]> {
self.into_vec().into_boxed_slice()
}
pub fn leak<'a>(self) -> &'a mut [$item_ty]
where
$item_ty: 'a
{
self.into_vec().leak()
}
pub fn reduce(self, f: impl FnMut($item_ty, $item_ty) -> $item_ty) -> $item_ty {
self.into_iter().reduce(f).unwrap()
}
pub fn reduce_ref<'a>(&'a self, f: impl FnMut(&'a $item_ty, &'a $item_ty) -> &'a $item_ty) -> &'a $item_ty {
self.iter().reduce(f).unwrap()
}
pub fn reduce_mut<'a>(&'a mut self, f: impl FnMut(&'a mut $item_ty, &'a mut $item_ty) -> &'a mut $item_ty) -> &'a mut $item_ty {
self.iter_mut().reduce(f).unwrap()
}
}
impl_wrapper! {
base_bounds_macro = $($tb : $trait)?,
impl<$t> $name<$t> {
fn append(&mut self, other: &mut $wrapped<$t>) -> ();
fn reserve(&mut self, additional: usize) -> ();
fn reserve_exact(&mut self, additional: usize) -> ();
fn shrink_to_fit(&mut self) -> ();
fn as_mut_slice(&mut self) -> &mut [$item_ty];
fn push(&mut self, value: $item_ty) -> ();
fn insert(&mut self, idx: usize, val: $item_ty) -> ();
fn len(&self) -> usize;
fn capacity(&self) -> usize;
fn as_slice(&self) -> &[$item_ty]
}
}
impl<$t> $name<$t>
where
$item_ty: PartialEq<$item_ty>,
$($tb : $trait,)?
{
pub fn dedup(&mut self) {
self.0.dedup()
}
}
impl<$t> $name<$t>
where
$item_ty: Copy,
$($tb : $trait,)?
{
pub fn extend_from_slice(&mut self, slice: &[$item_ty]) {
self.0.extend_from_slice(slice)
}
}
impl<$t> $name<$t>
where
$item_ty: Clone,
$($tb : $trait,)?
{
pub fn resize(&mut self, len: usize, value: $item_ty) -> Result<(), Size0Error> {
if len == 0 {
Err(Size0Error)
} else {
self.0.resize(len, value);
Ok(())
}
}
#[deprecated(
since = "1.8.0",
note = "try_ prefix created ambiguity use `resize_with`"
)]
#[inline(always)]
pub fn try_resize(&mut self, len: usize, value: $item_ty) -> Result<(), Size0Error> {
self.resize(len, value)
}
}
impl<$t> From<$name<$t>> for $wrapped<$t>
where
$($tb : $trait,)?
{
fn from(vec: $name<$t>) -> $wrapped<$t> {
vec.0
}
}
impl<$t> TryFrom<$wrapped<$t>> for $name<$t>
where
$($tb : $trait,)?
{
type Error = Size0Error;
fn try_from(vec: $wrapped<$t>) -> Result<Self, Size0Error> {
if vec.is_empty() {
Err(Size0Error)
} else {
Ok(Self(vec))
}
}
}
impl<$t> TryFrom<&'_ [$item_ty]> for $name<$t>
where
$item_ty: Clone,
$($tb : $trait,)?
{
type Error = Size0Error;
fn try_from(slice: &'_ [$item_ty]) -> Result<Self, Size0Error> {
if slice.is_empty() {
Err(Size0Error)
} else {
Ok($name($wrapped::from(slice)))
}
}
}
impl<$t> TryFrom<Box<[$item_ty]>> for $name<$t>
where
$($tb : $trait,)?
{
type Error = Size0Error;
fn try_from(slice: Box<[$item_ty]>) -> Result<Self, Size0Error> {
if slice.is_empty() {
Err(Size0Error)
} else {
let vec = Vec::from(slice);
Self::try_from_vec(vec)
}
}
}
impl<$t> Debug for $name<$t>
where
$item_ty: Debug,
$($tb : $trait,)?
{
#[inline]
fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.0, fter)
}
}
impl<$t> Clone for $name<$t>
where
$item_ty: Clone,
$($tb : $trait,)?
{
#[inline]
fn clone(&self) -> Self {
$name(self.0.clone())
}
}
impl<$t, B> PartialEq<B> for $name<$t>
where
B: ?Sized,
$wrapped<$t>: PartialEq<B>,
$($tb : $trait,)?
{
#[inline]
fn eq(&self, other: &B) -> bool {
self.0.eq(other)
}
}
impl<$t> Eq for $name<$t>
where
$item_ty: Eq,
$($tb : $trait,)?
{}
impl<$t> Hash for $name<$t>
where
$item_ty: Hash,
$($tb : $trait,)?
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}
impl<$t> PartialOrd for $name<$t>
where
$item_ty: PartialOrd,
$($tb : $trait,)?
{
#[inline]
fn partial_cmp(&self, other: &$name<$t>) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<$t> Ord for $name<$t>
where
$item_ty: Ord,
$($tb : $trait,)?
{
#[inline]
fn cmp(&self, other: &$name<$t>) -> Ordering {
self.0.cmp(&other.0)
}
}
impl<$t> Deref for $name<$t>
where
$($tb : $trait,)?
{
type Target = [$item_ty];
fn deref(&self) -> &Self::Target {
&*self.0
}
}
impl<$t> DerefMut for $name<$t>
where
$($tb : $trait,)?
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.0
}
}
impl<'a, $t> IntoIterator for &'a $name<$t>
where
$($tb : $trait,)?
{
type Item = &'a $item_ty;
type IntoIter = core::slice::Iter<'a, $item_ty>;
fn into_iter(self) -> Self::IntoIter {
(&self.0).into_iter()
}
}
impl<'a, $t> IntoIterator for &'a mut $name<$t>
where
$($tb : $trait,)?
{
type Item = &'a mut $item_ty;
type IntoIter = core::slice::IterMut<'a, $item_ty>;
fn into_iter(self) -> Self::IntoIter {
(&mut self.0).into_iter()
}
}
impl<$t> Default for $name<$t>
where
$item_ty: Default,
$($tb : $trait,)?
{
fn default() -> Self {
$name::new(Default::default())
}
}
impl<$t> AsRef<[$item_ty]> for $name<$t>
where
$($tb : $trait,)?
{
fn as_ref(&self) -> &[$item_ty] {
self.0.as_ref()
}
}
impl<$t> AsMut<[$item_ty]> for $name<$t>
where
$($tb : $trait,)?
{
fn as_mut(&mut self) -> &mut [$item_ty] {
self.0.as_mut()
}
}
impl<$t> AsRef<$wrapped<$t>> for $name<$t>
where
$($tb : $trait,)?
{
fn as_ref(&self) -> &$wrapped<$t>{
&self.0
}
}
impl<$t> AsRef<$name<$t>> for $name<$t>
where
$($tb : $trait,)?
{
fn as_ref(&self) -> &$name<$t> {
self
}
}
impl<$t> AsMut<$name<$t>> for $name<$t>
where
$($tb : $trait,)?
{
fn as_mut(&mut self) -> &mut $name<$t> {
self
}
}
impl<$t> Borrow<[$item_ty]> for $name<$t>
where
$($tb : $trait,)?
{
fn borrow(&self) -> &[$item_ty] {
self.0.as_ref()
}
}
impl<$t> Borrow<$wrapped<$t>> for $name<$t>
where
$($tb : $trait,)?
{
fn borrow(&self) -> &$wrapped<$t>{
&self.0
}
}
impl<$t, SI> Index<SI> for $name<$t>
where
SI: SliceIndex<[$item_ty]>,
$($tb : $trait,)?
{
type Output = SI::Output;
fn index(&self, index: SI) -> &SI::Output {
self.0.index(index)
}
}
impl<$t, SI> IndexMut<SI> for $name<$t>
where
SI: SliceIndex<[$item_ty]>,
$($tb : $trait,)?
{
fn index_mut(&mut self, index: SI) -> &mut SI::Output {
self.0.index_mut(index)
}
}
impl<$t> BorrowMut<[$item_ty]> for $name<$t>
where
$($tb : $trait,)?
{
fn borrow_mut(&mut self) -> &mut [$item_ty] {
self.0.as_mut()
}
}
impl<$t> Extend<$item_ty> for $name<$t>
where
$($tb : $trait,)?
{
fn extend<IT: IntoIterator<Item = $item_ty>>(&mut self, iterable: IT) {
self.0.extend(iterable)
}
}
#[cfg(feature = "serde")]
const _: () = {
use core::marker::PhantomData;
use serde::{
de::{SeqAccess,Deserialize, Visitor, Deserializer, Error as _},
ser::{Serialize, Serializer, SerializeSeq}
};
impl<$t> Serialize for $name<$t>
where
$item_ty: Serialize,
$($tb : $trait,)?
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut seq_ser = serializer.serialize_seq(Some(self.len()))?;
for item in self {
seq_ser.serialize_element(&item)?;
}
seq_ser.end()
}
}
impl<'de, $t> Deserialize<'de> for $name<$t>
where
$item_ty: Deserialize<'de>,
$($tb : $trait,)?
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_seq(SmallVec1Visitor {
_type_carry: PhantomData,
})
}
}
struct SmallVec1Visitor<$t> {
_type_carry: PhantomData<$t>,
}
impl<'de, $t> Visitor<'de> for SmallVec1Visitor<$t>
where
$item_ty: Deserialize<'de>,
$($tb : $trait,)?
{
type Value = $name<$t>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a sequence")
}
fn visit_seq<B>(self, mut seq: B) -> Result<Self::Value, B::Error>
where
B: SeqAccess<'de>,
{
let len = seq.size_hint().unwrap_or(0);
let mut vec = $wrapped::new();
vec.reserve(len);
while let Some(value) = seq.next_element()? {
vec.push(value);
}
$name::try_from(vec).map_err(B::Error::custom)
}
}
};
);
}
#[cfg(test)]
mod tests {
use core::ops::{Bound, RangeBounds};
#[derive(Debug)]
struct AnyBound {
start: Bound<usize>,
end: Bound<usize>,
}
fn bound_as_ref(bound: &Bound<usize>) -> Bound<&usize> {
match bound {
Bound::Included(v) => Bound::Included(v),
Bound::Excluded(v) => Bound::Excluded(v),
Bound::Unbounded => Bound::Unbounded,
}
}
impl RangeBounds<usize> for AnyBound {
fn start_bound(&self) -> Bound<&usize> {
bound_as_ref(&self.start)
}
fn end_bound(&self) -> Bound<&usize> {
bound_as_ref(&self.end)
}
}
mod range_covers_slice_start {
use super::super::range_covers_slice_start;
use core::ops::Bound;
#[test]
fn included_bound() {
let cases = &[
(1, 10, (false, false)),
(0, 0, (true, false)),
(0, 1, (true, false)),
(1, 0, (false, true)),
(11, 10, (false, true)),
(1, 1, (false, false)),
];
for (start, len, expected_res) in cases {
let res = range_covers_slice_start(Bound::Included(start), *len);
assert_eq!(
res, *expected_res,
"Failed start=${}, len=${}, res]=${:?}",
start, len, res
);
}
}
#[test]
fn excluded_bound() {
let cases = &[
(1, 10, (false, false)),
(0, 0, (false, true)),
(0, 1, (false, false)),
(1, 0, (false, true)),
(11, 10, (false, true)),
(1, 1, (false, true)),
];
for (start, len, expected_res) in cases {
let res = range_covers_slice_start(Bound::Excluded(start), *len);
assert_eq!(
res, *expected_res,
"Failed start=${}, len=${}, res]=${:?}",
start, len, res
);
}
}
#[test]
fn unbound_bound() {
for len in &[0, 1, 100] {
assert_eq!(
range_covers_slice_start(Bound::Unbounded, *len),
(true, false)
);
}
}
}
mod range_covers_slice_end {
use super::super::range_covers_slice_end;
use core::ops::Bound;
#[test]
fn included_bound() {
let cases = &[
(5, 6, (true, false)),
(4, 6, (false, false)),
(0, 10, (false, false)),
(6, 6, (true, true)),
(9, 8, (true, true)),
(0, 0, (true, true)),
];
for (end, len, expected_res) in cases {
let res = range_covers_slice_end(Bound::Included(end), *len);
assert_eq!(
res, *expected_res,
"Failed start=${}, len=${}, res]=${:?}",
end, len, res
);
}
}
#[test]
fn excluded_bound() {
let cases = &[
(5, 6, (false, false)),
(4, 6, (false, false)),
(0, 10, (false, false)),
(6, 6, (true, false)),
(0, 0, (true, false)),
(11, 10, (true, true)),
(1, 0, (true, true)),
];
for (end, len, expected_res) in cases {
let res = range_covers_slice_end(Bound::Excluded(end), *len);
assert_eq!(
res, *expected_res,
"Unexpected result: start=${}, len=${}, res=${:?} => ${:?}",
end, len, res, expected_res
);
}
}
#[test]
fn unbound_bound() {
for len in &[0, 1, 100] {
assert_eq!(
range_covers_slice_end(Bound::Unbounded, *len),
(true, false)
);
}
}
}
mod range_covers_slice {
use super::super::range_covers_slice;
use super::AnyBound;
#[test]
fn test_multiple_cases_from_table() {
use core::ops::Bound::*;
let len = 3;
let cases: &[_] = &[
(Included(0), Excluded(len), (true, false)),
(Unbounded, Excluded(len - 1), (false, false)),
(Included(0), Included(len), (true, true)),
(Included(1), Included(len - 1), (false, false)),
(Excluded(0), Included(len - 2), (false, false)),
(Included(1), Excluded(len + 4), (false, true)),
(Excluded(len), Excluded(len), (false, true)),
(Included(len + 1), Excluded(len - 1), (false, true)),
(Excluded(len), Included(len), (false, true)),
];
for &(start, end, expected_res) in cases.into_iter() {
let bound = AnyBound { start, end };
let res = range_covers_slice(&bound, len);
assert_eq!(
res, expected_res,
"Unexpected result: bound=${:?}, len=${} => ${:?}",
bound, len, expected_res
)
}
}
}
}