use serde::{
Deserialize, Serialize,
de::Error,
ser::{SerializeSeq, Serializer},
};
use smallvec::SmallVec;
use std::convert::TryFrom;
use std::iter;
use std::mem;
use std::{cmp::Ordering, num::NonZeroUsize};
#[macro_export]
#[doc(hidden)]
macro_rules! __non_empty_smallvec {
($h:expr, $( $x:expr ),* $(,)?) => {{
let tail = $crate::collections::smallvec::smallvec![$($x),*];
$crate::collections::NonEmptySmallVec { head: $h, tail }
}};
($h:expr, $( $x:expr ),* ; _) => {{
let tail = $crate::collections::smallvec::smallvec![$($x),*];
const N: usize = $crate::macros::count!($($x)*);
$crate::collections::NonEmptySmallVec::<N, _> { head: $h, tail }
}};
($h:expr, $( $x:expr ),* ; $N:literal) => {{
let tail = $crate::collections::smallvec::smallvec![$($x),*];
$crate::collections::NonEmptySmallVec::<$N, _> { head: $h, tail }
}};
($h:expr) => {
$crate::collections::NonEmptySmallVec {
head: $h,
tail: $crate::collections::smallvec::smallvec![],
}
};
($h:expr; _) => {
$crate::collections::NonEmptySmallVec {
head: $h,
tail: $crate::collections::smallvec::SmallVec::<[_; 0]>::new(),
}
};
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NonEmptySmallVec<const N: usize, T> {
pub head: T,
pub tail: SmallVec<[T; N]>,
}
impl<const N: usize, T: Serialize> Serialize for NonEmptySmallVec<N, T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.len()))?;
for e in self {
seq.serialize_element(e)?;
}
seq.end()
}
}
impl<'de, const N: usize, T: Deserialize<'de>> Deserialize<'de> for NonEmptySmallVec<N, T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
<SmallVec<[T; N]>>::deserialize(deserializer)?
.try_into()
.map_err(D::Error::custom)
}
}
pub struct NonEmptySmallVecIter<'a, T> {
head: Option<&'a T>,
tail: &'a [T],
}
impl<'a, T> Iterator for NonEmptySmallVecIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if let Some(value) = self.head.take() {
Some(value)
} else if let Some((first, rest)) = self.tail.split_first() {
self.tail = rest;
Some(first)
} else {
None
}
}
}
impl<T> DoubleEndedIterator for NonEmptySmallVecIter<'_, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if let Some((last, rest)) = self.tail.split_last() {
self.tail = rest;
Some(last)
} else if let Some(first_value) = self.head.take() {
Some(first_value)
} else {
None
}
}
}
impl<T> ExactSizeIterator for NonEmptySmallVecIter<'_, T> {
fn len(&self) -> usize {
self.tail.len() + self.head.map_or(0, |_| 1)
}
}
impl<T> std::iter::FusedIterator for NonEmptySmallVecIter<'_, T> {}
impl<const N: usize, T> NonEmptySmallVec<N, T> {
pub fn new(e: T) -> Self {
Self::singleton(e)
}
pub fn as_ref(&self) -> NonEmptySmallVec<N, &T> {
NonEmptySmallVec {
head: &self.head,
tail: self.tail.iter().collect(),
}
}
pub fn collect<I>(iter: I) -> Option<Self>
where
I: IntoIterator<Item = T>,
{
let mut iter = iter.into_iter();
let head = iter.next()?;
Some(Self {
head,
tail: iter.collect(),
})
}
pub fn singleton(head: T) -> Self {
Self {
head,
tail: SmallVec::new(),
}
}
pub const fn is_empty(&self) -> bool {
false
}
pub const fn first(&self) -> &T {
&self.head
}
pub fn first_mut(&mut self) -> &mut T {
&mut self.head
}
pub fn tail(&self) -> &[T] {
&self.tail
}
pub fn push(&mut self, e: T) {
self.tail.push(e)
}
pub fn pop(&mut self) -> Option<T> {
self.tail.pop()
}
pub fn insert(&mut self, index: usize, element: T) {
let len = self.len();
assert!(index <= len);
if index == 0 {
let head = mem::replace(&mut self.head, element);
self.tail.insert(0, head);
} else {
self.tail.insert(index - 1, element);
}
}
pub fn len(&self) -> usize {
self.tail.len() + 1
}
pub fn len_nonzero(&self) -> NonZeroUsize {
unsafe { NonZeroUsize::new_unchecked(self.tail.len().saturating_add(1)) }
}
pub fn capacity(&self) -> NonZeroUsize {
NonZeroUsize::MIN.saturating_add(self.tail.capacity())
}
pub fn last(&self) -> &T {
match self.tail.last() {
None => &self.head,
Some(e) => e,
}
}
pub fn last_mut(&mut self) -> &mut T {
match self.tail.last_mut() {
None => &mut self.head,
Some(e) => e,
}
}
pub fn contains(&self, x: &T) -> bool
where
T: PartialEq,
{
self.iter().any(|e| e == x)
}
pub fn get(&self, index: usize) -> Option<&T> {
if index == 0 {
Some(&self.head)
} else {
self.tail.get(index - 1)
}
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index == 0 {
Some(&mut self.head)
} else {
self.tail.get_mut(index - 1)
}
}
pub fn truncate(&mut self, len: NonZeroUsize) {
self.tail.truncate(len.get() - 1);
}
pub fn iter(&self) -> NonEmptySmallVecIter<'_, T> {
NonEmptySmallVecIter {
head: Some(&self.head),
tail: &self.tail,
}
}
pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut T> + '_ {
iter::once(&mut self.head).chain(self.tail.iter_mut())
}
pub fn from_slice(slice: &[T]) -> Option<Self>
where
T: Clone,
{
slice.split_first().map(|(h, t)| Self {
head: h.clone(),
tail: t.into(),
})
}
#[must_use]
pub fn from_smallvec(mut vec: SmallVec<[T; N]>) -> Option<Self> {
if vec.is_empty() {
None
} else {
let head = vec.remove(0);
Some(Self { head, tail: vec })
}
}
pub fn split_first(&self) -> (&T, &[T]) {
(&self.head, &self.tail)
}
pub fn split(&self) -> (&T, &[T], Option<&T>) {
match self.tail.split_last() {
None => (&self.head, &[], None),
Some((last, middle)) => (&self.head, middle, Some(last)),
}
}
pub fn append(&mut self, other: &mut SmallVec<[T; N]>) {
self.tail.append(other)
}
pub fn map<U, F>(self, mut f: F) -> NonEmptySmallVec<N, U>
where
F: FnMut(T) -> U,
{
NonEmptySmallVec {
head: f(self.head),
tail: self.tail.into_iter().map(f).collect(),
}
}
pub fn try_map<E, U, F>(self, mut f: F) -> Result<NonEmptySmallVec<N, U>, E>
where
F: FnMut(T) -> Result<U, E>,
{
Ok(NonEmptySmallVec {
head: f(self.head)?,
tail: self.tail.into_iter().map(f).collect::<Result<_, _>>()?,
})
}
pub fn flat_map<U, F>(self, mut f: F) -> NonEmptySmallVec<N, U>
where
F: FnMut(T) -> NonEmptySmallVec<N, U>,
{
let mut heads = f(self.head);
let mut tails = self
.tail
.into_iter()
.flat_map(|t| f(t).into_iter())
.collect();
heads.append(&mut tails);
heads
}
pub fn flatten(full: NonEmptySmallVec<N, Self>) -> Self {
full.flat_map(|n| n)
}
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
where
T: Ord,
{
self.binary_search_by(|p| p.cmp(x))
}
pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
where
F: FnMut(&'a T) -> Ordering,
{
match f(&self.head) {
Ordering::Equal => Ok(0),
Ordering::Greater => Err(0),
Ordering::Less => self
.tail
.binary_search_by(f)
.map(|index| index + 1)
.map_err(|index| index + 1),
}
}
pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
where
B: Ord,
F: FnMut(&'a T) -> B,
{
self.binary_search_by(|k| f(k).cmp(b))
}
pub fn maximum(&self) -> &T
where
T: Ord,
{
self.maximum_by(|i, j| i.cmp(j))
}
pub fn minimum(&self) -> &T
where
T: Ord,
{
self.minimum_by(|i, j| i.cmp(j))
}
pub fn maximum_by<F>(&self, mut compare: F) -> &T
where
F: FnMut(&T, &T) -> Ordering,
{
let mut max = &self.head;
for i in self.tail.iter() {
max = match compare(max, i) {
Ordering::Equal | Ordering::Greater => max,
Ordering::Less => i,
};
}
max
}
pub fn minimum_by<F>(&self, mut compare: F) -> &T
where
F: FnMut(&T, &T) -> Ordering,
{
self.maximum_by(|a, b| compare(a, b).reverse())
}
pub fn maximum_by_key<U, F>(&self, mut f: F) -> &T
where
U: Ord,
F: FnMut(&T) -> U,
{
self.maximum_by(|i, j| f(i).cmp(&f(j)))
}
pub fn minimum_by_key<U, F>(&self, mut f: F) -> &T
where
U: Ord,
F: FnMut(&T) -> U,
{
self.minimum_by(|i, j| f(i).cmp(&f(j)))
}
pub fn sort(&mut self)
where
T: Ord,
{
self.tail.sort();
let index = self.tail.partition_point(|x| x < &self.head);
if index != 0 {
let new_head = self.tail.remove(0);
let head = mem::replace(&mut self.head, new_head);
self.tail.insert(index - 1, head);
}
}
pub fn sort_by<F>(&mut self, mut compare: F)
where
F: FnMut(&T, &T) -> Ordering,
{
self.tail.sort_by(&mut compare);
let index = self
.tail
.partition_point(|x| compare(x, &self.head) == Ordering::Less);
if index != 0 {
let new_head = self.tail.remove(0);
let head = mem::replace(&mut self.head, new_head);
self.tail.insert(index - 1, head);
}
}
pub fn sort_by_key<K, F>(&mut self, mut f: F)
where
F: FnMut(&T) -> K,
K: Ord,
{
self.tail.sort_by_key(&mut f);
let head_key = f(&self.head);
let index = self.tail.partition_point(|x| f(x) < head_key);
if index != 0 {
let new_head = self.tail.remove(0);
let head = mem::replace(&mut self.head, new_head);
self.tail.insert(index - 1, head);
}
}
pub fn sort_by_cached_key<K, F>(&mut self, mut f: F)
where
F: FnMut(&T) -> K,
K: Ord,
{
self.tail.sort_by_cached_key(&mut f);
let head_key = f(&self.head);
let index = self.tail.partition_point(|x| f(x) < head_key);
if index != 0 {
let new_head = self.tail.remove(0);
let head = mem::replace(&mut self.head, new_head);
self.tail.insert(index - 1, head);
}
}
}
impl<const N: usize, T: Default> Default for NonEmptySmallVec<N, T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<const N: usize, T> From<NonEmptySmallVec<N, T>> for SmallVec<[T; N]> {
fn from(non_empty_smallvec: NonEmptySmallVec<N, T>) -> Self {
let NonEmptySmallVec { head, mut tail } = non_empty_smallvec;
tail.insert(0, head);
tail
}
}
impl<const N: usize, T> From<NonEmptySmallVec<N, T>> for (T, SmallVec<[T; N]>) {
fn from(non_empty_smallvec: NonEmptySmallVec<N, T>) -> (T, SmallVec<[T; N]>) {
(non_empty_smallvec.head, non_empty_smallvec.tail)
}
}
impl<const N: usize, T> From<(T, SmallVec<[T; N]>)> for NonEmptySmallVec<N, T> {
fn from((head, tail): (T, SmallVec<[T; N]>)) -> Self {
Self { head, tail }
}
}
impl<const N: usize, T> IntoIterator for NonEmptySmallVec<N, T> {
type Item = T;
type IntoIter = iter::Chain<iter::Once<T>, smallvec::IntoIter<[Self::Item; N]>>;
fn into_iter(self) -> Self::IntoIter {
iter::once(self.head).chain(self.tail)
}
}
impl<'a, const N: usize, T> IntoIterator for &'a NonEmptySmallVec<N, T> {
type Item = &'a T;
type IntoIter = iter::Chain<iter::Once<&'a T>, std::slice::Iter<'a, T>>;
fn into_iter(self) -> Self::IntoIter {
iter::once(&self.head).chain(self.tail.iter())
}
}
impl<const N: usize, T> std::ops::Index<usize> for NonEmptySmallVec<N, T> {
type Output = T;
fn index(&self, index: usize) -> &T {
if index > 0 {
&self.tail[index - 1]
} else {
&self.head
}
}
}
impl<const N: usize, T> std::ops::IndexMut<usize> for NonEmptySmallVec<N, T> {
fn index_mut(&mut self, index: usize) -> &mut T {
if index > 0 {
&mut self.tail[index - 1]
} else {
&mut self.head
}
}
}
impl<const N: usize, A> Extend<A> for NonEmptySmallVec<N, A> {
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
self.tail.extend(iter)
}
}
impl<const N: usize, T> TryFrom<SmallVec<[T; N]>> for NonEmptySmallVec<N, T> {
type Error = NonEmptySmallVecEmptyError;
fn try_from(vec: SmallVec<[T; N]>) -> Result<Self, Self::Error> {
Self::from_smallvec(vec).ok_or(NonEmptySmallVecEmptyError)
}
}
crate::macros::error::static_str_error! {
#[doc = "empty value cannot be turned into a NonEmptySmallVec"]
pub struct NonEmptySmallVecEmptyError;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::collections::non_empty_smallvec;
use smallvec::smallvec;
#[test]
fn test_from_conversion() {
let result: NonEmptySmallVec<4, _> = NonEmptySmallVec::from((1, smallvec![2, 3, 4, 5]));
let expected: NonEmptySmallVec<4, _> = NonEmptySmallVec {
head: 1,
tail: smallvec![2, 3, 4, 5],
};
assert_eq!(result, expected);
}
#[test]
fn test_into_iter() {
let non_empty_smallvec: NonEmptySmallVec<3, _> =
NonEmptySmallVec::from((0, smallvec![1, 2, 3]));
for (i, n) in non_empty_smallvec.into_iter().enumerate() {
assert_eq!(i as i32, n);
}
}
#[test]
fn test_iter_syntax() {
let non_empty_smallvec: NonEmptySmallVec<3, _> =
NonEmptySmallVec::from((0, smallvec![1, 2, 3]));
for n in &non_empty_smallvec {
let _ = *n; }
for _ in non_empty_smallvec {}
}
#[test]
fn test_iter_both_directions() {
let mut non_empty_smallvec: NonEmptySmallVec<3, _> =
NonEmptySmallVec::from((0, smallvec![1, 2, 3]));
assert_eq!(
non_empty_smallvec.iter().cloned().collect::<Vec<_>>(),
[0, 1, 2, 3]
);
assert_eq!(
non_empty_smallvec.iter().rev().cloned().collect::<Vec<_>>(),
[3, 2, 1, 0]
);
assert_eq!(
non_empty_smallvec.iter_mut().rev().collect::<Vec<_>>(),
[&mut 3, &mut 2, &mut 1, &mut 0]
);
}
#[test]
fn test_iter_both_directions_at_once() {
let non_empty_smallvec: NonEmptySmallVec<3, _> =
NonEmptySmallVec::from((0, smallvec![1, 2, 3]));
let mut i = non_empty_smallvec.iter();
assert_eq!(i.next(), Some(&0));
assert_eq!(i.next_back(), Some(&3));
assert_eq!(i.next(), Some(&1));
assert_eq!(i.next_back(), Some(&2));
assert_eq!(i.next(), None);
assert_eq!(i.next_back(), None);
}
#[test]
fn test_mutate_head() {
let mut non_empty: NonEmptySmallVec<0, _> = NonEmptySmallVec::new(42);
non_empty.head += 1;
assert_eq!(non_empty.head, 43);
let mut non_empty: NonEmptySmallVec<3, _> = NonEmptySmallVec::from((1, smallvec![4, 2, 3]));
non_empty.head *= 42;
assert_eq!(non_empty.head, 42);
}
#[test]
fn test_to_nonempty() {
use std::iter::{empty, once};
assert_eq!(NonEmptySmallVec::<0, ()>::collect(empty()), None);
assert_eq!(
NonEmptySmallVec::<0, ()>::collect(once(())),
Some(NonEmptySmallVec::new(()))
);
assert_eq!(
NonEmptySmallVec::<1, u8>::collect(once(1).chain(once(2))),
Some(non_empty_smallvec!(1, 2))
);
}
#[test]
fn test_try_map() {
assert_eq!(
non_empty_smallvec!(1, 2, 3, 4; 4).try_map(Ok::<_, String>),
Ok(non_empty_smallvec!(1, 2, 3, 4; 4))
);
assert_eq!(
non_empty_smallvec!(1, 2, 3, 4; 4).try_map(|i| if i % 2 == 0 {
Ok(i)
} else {
Err("not even")
}),
Err("not even")
);
}
#[test]
fn test_nontrivial_minimum_by_key() {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Position {
x: i32,
y: i32,
}
impl Position {
pub(super) fn distance_squared(self, other: Self) -> u32 {
let dx = self.x - other.x;
let dy = self.y - other.y;
(dx * dx + dy * dy) as u32
}
}
let positions = non_empty_smallvec![
Position { x: 1, y: 1 },
Position { x: 0, y: 0 },
Position { x: 3, y: 4 }
; _
];
let target = Position { x: 1, y: 2 };
let closest = positions.minimum_by_key(|position| position.distance_squared(target));
assert_eq!(closest, &Position { x: 1, y: 1 });
}
#[test]
fn test_sort() {
let mut numbers = non_empty_smallvec![1; _];
numbers.sort();
assert_eq!(numbers, non_empty_smallvec![1; _]);
let mut numbers = non_empty_smallvec![2, 1, 3; _];
numbers.sort();
assert_eq!(numbers, non_empty_smallvec![1, 2, 3; _]);
let mut numbers = non_empty_smallvec![1, 3, 2; _];
numbers.sort();
assert_eq!(numbers, non_empty_smallvec![1, 2, 3; _]);
let mut numbers = non_empty_smallvec![3, 2, 1; _];
numbers.sort();
assert_eq!(numbers, non_empty_smallvec![1, 2, 3; _]);
}
#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
struct SimpleSerializable(pub i32);
#[test]
fn test_simple_round_trip() -> Result<(), Box<dyn std::error::Error>> {
let mut non_empty = NonEmptySmallVec::new(SimpleSerializable(42));
non_empty.push(SimpleSerializable(777));
let res = serde_json::from_str::<'_, NonEmptySmallVec<8, SimpleSerializable>>(
&serde_json::to_string(&non_empty)?,
)?;
assert_eq!(res, non_empty);
Ok(())
}
#[test]
fn test_serialization() -> Result<(), Box<dyn std::error::Error>> {
let ne = non_empty_smallvec![1, 2, 3, 4, 5; _];
let ve: SmallVec<[_; 5]> = smallvec![1, 2, 3, 4, 5];
assert_eq!(serde_json::to_string(&ne)?, serde_json::to_string(&ve)?);
Ok(())
}
}