//! Implement Fallible Vec
use super::TryClone;
use crate::TryReserveError;
#[allow(unused_imports)]
use alloc::alloc::{alloc, realloc, Layout};
use alloc::vec::Vec;
use core::convert::TryInto as _;

#[cfg(feature = "unstable")]
#[macro_export]
/// macro trying to create a vec, return a
/// Result<Vec<T>,TryReserveError>
macro_rules! try_vec {
   ($elem:expr; $n:expr) => (
        $crate::vec::try_from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        match <alloc::boxed::Box<_> as $crate::boxed::FallibleBox<_>>::try_new([$($x),*]) {
            Err(e) => Err(e),
            Ok(b) => Ok(<[_]>::into_vec(b)),
        }
    );
    ($($x:expr,)*) => ($crate::try_vec![$($x),*])
}

/// trait implementing all fallible methods on vec
pub trait FallibleVec<T> {
    /// see reserve
    fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>;
    /// see push
    fn try_push(&mut self, elem: T) -> Result<(), TryReserveError>;
    /// try push and give back ownership in case of error
    fn try_push_give_back(&mut self, elem: T) -> Result<(), (T, TryReserveError)>;
    /// see with capacity, (Self must be sized by the constraint of Result)
    fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError>
    where
        Self: core::marker::Sized;
    /// see insert
    fn try_insert(&mut self, index: usize, element: T) -> Result<(), (T, TryReserveError)>;
    /// see append
    fn try_append(&mut self, other: &mut Self) -> Result<(), TryReserveError>;
    /// see resize, only works when the `value` implements Copy, otherwise, look at try_resize_no_copy
    fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
    where
        T: Copy + Clone;
    fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), TryReserveError>
    where
        F: FnMut() -> T;
    /// resize the vec by trying to clone the value repeatingly
    fn try_resize_no_copy(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
    where
        T: TryClone;
    /// see resize, only works when the `value` implements Copy, otherwise, look at try_extend_from_slice_no_copy
    fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError>
    where
        T: Copy + Clone;
    /// extend the vec by trying to clone the value in `other`
    fn try_extend_from_slice_no_copy(&mut self, other: &[T]) -> Result<(), TryReserveError>
    where
        T: TryClone;
}

/// TryVec is a thin wrapper around alloc::vec::Vec to provide support for
/// fallible allocation.
///
/// See the crate documentation for more.
#[derive(PartialEq)]
pub struct TryVec<T> {
    inner: Vec<T>,
}

impl<T> Default for TryVec<T> {
    #[inline(always)]
    fn default() -> Self {
        Self {
            inner: Default::default(),
        }
    }
}

impl<T: core::fmt::Debug> core::fmt::Debug for TryVec<T> {
    #[inline]
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        self.inner.fmt(f)
    }
}

impl<T> TryVec<T> {
    #[inline(always)]
    pub fn new() -> Self {
        Self { inner: Vec::new() }
    }

    #[inline]
    pub fn with_capacity(capacity: usize) -> Result<Self, TryReserveError> {
        Ok(Self {
            inner: FallibleVec::try_with_capacity(capacity)?,
        })
    }

    #[inline(always)]
    pub fn append(&mut self, other: &mut Self) -> Result<(), TryReserveError> {
        FallibleVec::try_append(&mut self.inner, &mut other.inner)
    }

    #[inline(always)]
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }

    #[inline(always)]
    pub fn as_slice(&self) -> &[T] {
        self
    }

    #[inline(always)]
    pub fn clear(&mut self) {
        self.inner.clear()
    }

    #[cfg(test)]
    pub fn into_inner(self) -> Vec<T> {
        self.inner
    }

    #[inline(always)]
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }

    #[inline(always)]
    pub fn iter_mut(&mut self) -> IterMut<T> {
        IterMut {
            inner: self.inner.iter_mut(),
        }
    }

    #[inline(always)]
    pub fn iter(&self) -> Iter<T> {
        Iter {
            inner: self.inner.iter(),
        }
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<T> {
        self.inner.pop()
    }

    #[inline(always)]
    pub fn push(&mut self, value: T) -> Result<(), TryReserveError> {
        FallibleVec::try_push(&mut self.inner, value)
    }

    #[inline(always)]
    pub fn reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
        FallibleVec::try_reserve(&mut self.inner, additional)
    }

    #[inline(always)]
    pub fn resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), TryReserveError>
    where
        F: FnMut() -> T,
    {
        FallibleVec::try_resize_with(&mut self.inner, new_len, f)
    }
}

impl<T: TryClone> TryClone for TryVec<T> {
    #[inline]
    fn try_clone(&self) -> Result<Self, TryReserveError> {
        self.as_slice().try_into()
    }
}

impl<T: TryClone> TryVec<TryVec<T>> {
    pub fn concat(&self) -> Result<TryVec<T>, TryReserveError> {
        let size = self.iter().map(|v| v.inner.len()).sum();
        let mut result = TryVec::with_capacity(size)?;
        for v in self.iter() {
            result.inner.try_extend_from_slice_no_copy(&v.inner)?;
        }
        Ok(result)
    }
}

impl<T: TryClone> TryVec<T> {
    #[inline(always)]
    pub fn extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError> {
        self.inner.try_extend_from_slice_no_copy(other)
    }
}

impl<T> IntoIterator for TryVec<T> {
    type Item = T;
    type IntoIter = alloc::vec::IntoIter<T>;

    #[inline(always)]
    fn into_iter(self) -> Self::IntoIter {
        self.inner.into_iter()
    }
}

impl<'a, T> IntoIterator for &'a TryVec<T> {
    type Item = &'a T;
    type IntoIter = alloc::slice::Iter<'a, T>;

    #[inline(always)]
    fn into_iter(self) -> Self::IntoIter {
        self.inner.iter()
    }
}

#[cfg(feature = "std_io")]
pub mod std_io {
    use super::*;
    use std::io::{self, Read, Take, Write};

    pub trait TryRead {
        fn try_read_to_end(&mut self, buf: &mut TryVec<u8>) -> io::Result<usize>;

        #[inline]
        fn read_into_try_vec(&mut self) -> io::Result<TryVec<u8>> {
            let mut buf = TryVec::new();
            self.try_read_to_end(&mut buf)?;
            Ok(buf)
        }
    }

    impl<T: Read> TryRead for Take<T> {
        /// This function reserves the upper limit of what `src` can generate before
        /// reading all bytes until EOF in this source, placing them into `buf`. If the
        /// allocation is unsuccessful, or reading from the source generates an error
        /// before reaching EOF, this will return an error. Otherwise, it will return
        /// the number of bytes read.
        ///
        /// Since `Take::limit()` may return a value greater than the number of bytes
        /// which can be read from the source, it's possible this function may fail
        /// in the allocation phase even though allocating the number of bytes available
        /// to read would have succeeded. In general, it is assumed that the callers
        /// have accurate knowledge of the number of bytes of interest and have created
        /// `src` accordingly.
        #[inline]
        fn try_read_to_end(&mut self, buf: &mut TryVec<u8>) -> io::Result<usize> {
            try_read_up_to(self, self.limit(), buf)
        }
    }

    /// Read up to `limit` bytes from `src`, placing them into `buf` and returning the
    /// number of bytes read. Space for `limit` additional bytes is reserved in `buf`, so
    /// this function will return an error if the allocation fails.
    pub fn try_read_up_to<R: Read>(
        src: &mut R,
        limit: u64,
        buf: &mut TryVec<u8>,
    ) -> io::Result<usize> {
        let additional = limit
            .try_into()
            .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
        buf.reserve(additional)
            .map_err(|_| io::Error::new(io::ErrorKind::Other, "reserve allocation failed"))?;
        let bytes_read = src.take(limit).read_to_end(&mut buf.inner)?;
        Ok(bytes_read)
    }

    impl Write for TryVec<u8> {
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            self.extend_from_slice(buf)
                .map_err(|_| io::Error::new(io::ErrorKind::Other, "extend_from_slice failed"))?;
            Ok(buf.len())
        }

        #[inline(always)]
        fn flush(&mut self) -> io::Result<()> {
            Ok(())
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn try_read_to_end() {
            let mut src = b"1234567890".take(5);
            let mut buf = TryVec::new();
            src.try_read_to_end(&mut buf).unwrap();
            assert_eq!(buf.len(), 5);
            assert_eq!(buf, b"12345".as_ref());
        }

        #[test]
        fn read_into_try_vec() {
            let mut src = b"1234567890".take(5);
            let buf = src.read_into_try_vec().unwrap();
            assert_eq!(buf.len(), 5);
            assert_eq!(buf, b"12345".as_ref());
        }

        #[test]
        fn read_into_try_vec_oom() {
            let mut src = b"1234567890".take(core::usize::MAX.try_into().expect("usize < u64"));
            assert!(src.read_into_try_vec().is_err());
        }

        #[test]
        fn try_read_up_to() {
            let src = b"1234567890";
            let mut buf = TryVec::new();
            super::try_read_up_to(&mut src.as_ref(), 5, &mut buf).unwrap();
            assert_eq!(buf.len(), 5);
            assert_eq!(buf, b"12345".as_ref());
        }

        #[test]
        fn try_read_up_to_oom() {
            let src = b"1234567890";
            let mut buf = TryVec::new();
            let limit = core::usize::MAX.try_into().expect("usize < u64");
            let res = super::try_read_up_to(&mut src.as_ref(), limit, &mut buf);
            assert!(res.is_err());
        }
    }
}

impl<T: PartialEq> PartialEq<Vec<T>> for TryVec<T> {
    #[inline(always)]
    fn eq(&self, other: &Vec<T>) -> bool {
        self.inner.eq(other)
    }
}

impl<'a, T: PartialEq> PartialEq<&'a [T]> for TryVec<T> {
    #[inline(always)]
    fn eq(&self, other: &&[T]) -> bool {
        self.inner.eq(other)
    }
}

impl PartialEq<&str> for TryVec<u8> {
    #[inline]
    fn eq(&self, other: &&str) -> bool {
        self.as_slice() == other.as_bytes()
    }
}

impl core::convert::AsRef<[u8]> for TryVec<u8> {
    #[inline(always)]
    fn as_ref(&self) -> &[u8] {
        self.inner.as_ref()
    }
}

impl<T> core::convert::From<Vec<T>> for TryVec<T> {
    #[inline(always)]
    fn from(value: Vec<T>) -> Self {
        Self { inner: value }
    }
}

impl<T: TryClone> core::convert::TryFrom<&[T]> for TryVec<T> {
    type Error = TryReserveError;

    #[inline]
    fn try_from(value: &[T]) -> Result<Self, Self::Error> {
        let mut v = Self::new();
        v.inner.try_extend_from_slice_no_copy(value)?;
        Ok(v)
    }
}

impl core::convert::TryFrom<&str> for TryVec<u8> {
    type Error = TryReserveError;

    #[inline]
    fn try_from(value: &str) -> Result<Self, Self::Error> {
        let mut v = Self::new();
        v.extend_from_slice(value.as_bytes())?;
        Ok(v)
    }
}

impl<T> core::ops::Deref for TryVec<T> {
    type Target = [T];

    #[inline(always)]
    fn deref(&self) -> &[T] {
        self.inner.deref()
    }
}

impl<T> core::ops::DerefMut for TryVec<T> {
    fn deref_mut(&mut self) -> &mut [T] {
        self.inner.deref_mut()
    }
}

pub struct Iter<'a, T> {
    inner: alloc::slice::Iter<'a, T>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }

    #[inline(always)]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }
}

pub struct IterMut<'a, T> {
    inner: alloc::slice::IterMut<'a, T>,
}

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }

    #[inline(always)]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }
}

fn needs_to_grow<T>(v: &Vec<T>, len: usize) -> bool {
    v.len()
        .checked_add(len)
        .map_or(true, |needed| needed > v.capacity())
}

impl<T> FallibleVec<T> for Vec<T> {
    #[inline(always)]
    fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
        self.try_reserve(additional)
    }

    #[inline]
    fn try_push(&mut self, elem: T) -> Result<(), TryReserveError> {
        if self.len() == self.capacity() {
            self.try_reserve(1)?;
        }
        Ok(self.push(elem))
    }

    #[inline]
    fn try_push_give_back(&mut self, elem: T) -> Result<(), (T, TryReserveError)> {
        if self.len() == self.capacity() {
            if let Err(e) = self.try_reserve(1) {
                return Err((elem, e));
            }
        }
        Ok(self.push(elem))
    }

    #[inline]
    fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError>
    where
        Self: core::marker::Sized,
    {
        let mut n = Self::new();
        FallibleVec::try_reserve(&mut n, capacity)?;
        Ok(n)
    }

    #[inline]
    fn try_insert(&mut self, index: usize, element: T) -> Result<(), (T, TryReserveError)> {
        if self.len() == self.capacity() {
            if let Err(e) = self.try_reserve(1) {
                return Err((element, e));
            }
        }
        Ok(self.insert(index, element))
    }

    #[inline]
    fn try_append(&mut self, other: &mut Self) -> Result<(), TryReserveError> {
        FallibleVec::try_reserve(self, other.len())?;
        Ok(self.append(other))
    }

    fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
    where
        T: Copy + Clone,
    {
        let len = self.len();
        if new_len > len {
            FallibleVec::try_reserve(self, new_len - len)?;
        }
        Ok(self.resize(new_len, value))
    }

    fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), TryReserveError>
    where
        F: FnMut() -> T,
    {
        let len = self.len();
        if new_len > len {
            FallibleVec::try_reserve(self, new_len - len)?;
        }
        Ok(self.resize_with(new_len, f))
    }

    fn try_resize_no_copy(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
    where
        T: TryClone,
    {
        let len = self.len();

        if new_len > len {
            self.try_extend_with(new_len - len, TryExtendElement(value))
        } else {
            Ok(Truncate::truncate(self, new_len))
        }
    }

    #[inline]
    fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError>
    where
        T: Clone,
    {
        if needs_to_grow(self, other.len()) {
            self.try_reserve(other.len())?;
        }
        Ok(self.extend_from_slice(other))
    }

    fn try_extend_from_slice_no_copy(&mut self, other: &[T]) -> Result<(), TryReserveError>
    where
        T: TryClone,
    {
        if needs_to_grow(self, other.len()) {
            self.try_reserve(other.len())?;
        }
        let mut len = self.len();
        let mut iterator = other.iter();
        while let Some(element) = iterator.next() {
            unsafe {
                core::ptr::write(self.as_mut_ptr().add(len), element.try_clone()?);
                // NB can't overflow since we would have had to alloc the address space
                len += 1;
                self.set_len(len);
            }
        }
        Ok(())
    }
}

trait ExtendWith<T> {
    fn next(&mut self) -> Result<T, TryReserveError>;
    fn last(self) -> T;
}

struct TryExtendElement<T: TryClone>(T);
impl<T: TryClone> ExtendWith<T> for TryExtendElement<T> {
    #[inline(always)]
    fn next(&mut self) -> Result<T, TryReserveError> {
        self.0.try_clone()
    }
    #[inline(always)]
    fn last(self) -> T {
        self.0
    }
}

trait TryExtend<T> {
    fn try_extend_with<E: ExtendWith<T>>(
        &mut self,
        n: usize,
        value: E,
    ) -> Result<(), TryReserveError>;
}

impl<T> TryExtend<T> for Vec<T> {
    /// Extend the vector by `n` values, using the given generator.
    fn try_extend_with<E: ExtendWith<T>>(
        &mut self,
        n: usize,
        mut value: E,
    ) -> Result<(), TryReserveError> {
        if needs_to_grow(self, n) {
            self.try_reserve(n)?;
        }

        unsafe {
            let mut ptr = self.as_mut_ptr().add(self.len());

            let mut local_len = self.len();
            // Write all elements except the last one
            for _ in 1..n {
                core::ptr::write(ptr, value.next()?);
                ptr = ptr.offset(1);
                // Increment the length in every step in case next() panics
                local_len += 1;
                self.set_len(local_len);
            }

            if n > 0 {
                // We can write the last element directly without cloning needlessly
                core::ptr::write(ptr, value.last());
                local_len += 1;
                self.set_len(local_len);
            }

            // len set by scope guard
        }
        Ok(())
    }
}

trait Truncate {
    fn truncate(&mut self, len: usize);
}

impl<T> Truncate for Vec<T> {
    fn truncate(&mut self, len: usize) {
        let current_len = self.len();
        unsafe {
            let mut ptr = self.as_mut_ptr().add(current_len);
            // Set the final length at the end, keeping in mind that
            // dropping an element might panic. Works around a missed
            // optimization, as seen in the following issue:
            // https://github.com/rust-lang/rust/issues/51802
            let mut local_len = self.len();

            // drop any extra elements
            for _ in len..current_len {
                ptr = ptr.offset(-1);
                core::ptr::drop_in_place(ptr);
                local_len -= 1;
                self.set_len(local_len);
            }
        }
    }
}

/// try creating a vec from an `elem` cloned `n` times, see std::from_elem
#[cfg(feature = "unstable")]
pub fn try_from_elem<T: TryClone>(elem: T, n: usize) -> Result<Vec<T>, TryReserveError> {
    <T as SpecFromElem>::try_from_elem(elem, n)
}

// Specialization trait used for Vec::from_elem
#[cfg(feature = "unstable")]
trait SpecFromElem: Sized {
    fn try_from_elem(elem: Self, n: usize) -> Result<Vec<Self>, TryReserveError>;
}

#[cfg(feature = "unstable")]
impl<T: TryClone> SpecFromElem for T {
    default fn try_from_elem(elem: Self, n: usize) -> Result<Vec<T>, TryReserveError> {
        let mut v = Vec::new();
        v.try_resize_no_copy(n, elem)?;
        Ok(v)
    }
}

#[cfg(feature = "unstable")]
impl SpecFromElem for u8 {
    #[inline]
    fn try_from_elem(elem: u8, n: usize) -> Result<Vec<u8>, TryReserveError> {
        unsafe {
            let mut v: Vec<u8> = FallibleVec::try_with_capacity(n)?;
            core::ptr::write_bytes(v.as_mut_ptr(), elem, n);
            v.set_len(n);
            Ok(v)
        }
    }
}

impl<T: TryClone> TryClone for Vec<T> {
    #[inline]
    fn try_clone(&self) -> Result<Self, TryReserveError>
    where
        Self: core::marker::Sized,
    {
        let mut v = Vec::new();
        v.try_extend_from_slice_no_copy(self)?;
        Ok(v)
    }
}

pub trait TryFromIterator<I>: Sized {
    fn try_from_iterator<T: IntoIterator<Item = I>>(iterator: T) -> Result<Self, TryReserveError>;
}

impl<I> TryFromIterator<I> for Vec<I> {
    fn try_from_iterator<T: IntoIterator<Item = I>>(iterator: T) -> Result<Self, TryReserveError>
    where
        T: IntoIterator<Item = I>,
    {
        let mut new = Self::new();
        for i in iterator {
            new.try_push(i)?;
        }
        Ok(new)
    }
}

pub trait TryCollect<I> {
    fn try_collect<C: TryFromIterator<I>>(self) -> Result<C, TryReserveError>;
}

impl<I, T> TryCollect<I> for T
where
    T: IntoIterator<Item = I>,
{
    #[inline(always)]
    fn try_collect<C: TryFromIterator<I>>(self) -> Result<C, TryReserveError> {
        C::try_from_iterator(self)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    #[cfg(feature = "unstable")]
    fn vec() {
        // let v: Vec<u8> = from_elem(1, 10);
        let v: Vec<Vec<u8>> = try_vec![try_vec![42; 10].unwrap(); 100].unwrap();
        println!("{:?}", v);
        let v2 = try_vec![0, 1, 2];
        println!("{:?}", v2);
        assert_eq!(2 + 2, 4);
    }

    #[test]
    fn try_clone_vec() {
        // let v: Vec<u8> = from_elem(1, 10);
        let v = vec![42; 100];
        assert_eq!(v.try_clone().unwrap(), v);
    }

    #[test]
    fn try_clone_oom() {
        let layout = Layout::new::<u8>();
        let v = unsafe {
            Vec::<u8>::from_raw_parts(
                alloc(layout),
                core::isize::MAX as usize,
                core::isize::MAX as usize,
            )
        };
        assert!(v.try_clone().is_err());
    }

    #[test]
    fn tryvec_try_clone_oom() {
        let layout = Layout::new::<u8>();
        let inner = unsafe {
            Vec::<u8>::from_raw_parts(
                alloc(layout),
                core::isize::MAX as usize,
                core::isize::MAX as usize,
            )
        };
        let tv = TryVec { inner };
        assert!(tv.try_clone().is_err());
    }

    // #[test]
    // fn try_out_of_mem() {
    //     let v = try_vec![42_u8; 1000000000];
    //     assert_eq!(v.try_clone().unwrap(), v);
    // }

    #[test]
    fn oom() {
        let mut vec: Vec<char> = Vec::new();
        match FallibleVec::try_reserve(&mut vec, core::usize::MAX / std::mem::size_of::<char>()) {
            Ok(_) => panic!("it should be OOM"),
            _ => (),
        }
        match FallibleVec::try_reserve(&mut vec, core::usize::MAX) {
            Ok(_) => panic!("it should be OOM"),
            _ => (),
        }
    }

    #[test]
    fn tryvec_oom() {
        let mut vec: TryVec<char> = TryVec::new();
        match vec.reserve(core::usize::MAX / std::mem::size_of::<char>()) {
            Ok(_) => panic!("it should be OOM"),
            _ => (),
        }
        match vec.reserve(core::usize::MAX) {
            Ok(_) => panic!("it should be OOM"),
            _ => (),
        }
    }

    #[test]
    fn try_reserve() {
        let mut vec: Vec<_> = vec![1];
        let additional_room = vec.capacity() - vec.len();
        let additional = additional_room + 1;
        let old_cap = vec.capacity();
        FallibleVec::try_reserve(&mut vec, additional).unwrap();
        assert!(vec.capacity() > old_cap);
    }

    #[test]
    fn tryvec_reserve() {
        let mut vec: TryVec<_> = vec![1].into();
        let old_cap = vec.inner.capacity();
        let new_cap = old_cap + 1;
        vec.reserve(new_cap).unwrap();
        assert!(vec.inner.capacity() >= new_cap);
    }

    #[test]
    fn try_reserve_idempotent() {
        let mut vec: Vec<_> = vec![1];
        let additional_room = vec.capacity() - vec.len();
        let additional = additional_room + 1;
        FallibleVec::try_reserve(&mut vec, additional).unwrap();
        let cap_after_reserve = vec.capacity();
        FallibleVec::try_reserve(&mut vec, additional).unwrap();
        assert_eq!(vec.capacity(), cap_after_reserve);
    }

    #[test]
    fn tryvec_reserve_idempotent() {
        let mut vec: TryVec<_> = vec![1].into();
        let old_cap = vec.inner.capacity();
        let new_cap = old_cap + 1;
        vec.reserve(new_cap).unwrap();
        let cap_after_reserve = vec.inner.capacity();
        vec.reserve(new_cap).unwrap();
        assert_eq!(cap_after_reserve, vec.inner.capacity());
    }

    #[test]
    fn capacity_overflow() {
        let mut vec: Vec<_> = vec![1];
        match FallibleVec::try_reserve(&mut vec, core::usize::MAX) {
            Ok(_) => panic!("capacity calculation should overflow"),
            _ => (),
        }
    }

    #[test]
    fn tryvec_capacity_overflow() {
        let mut vec: TryVec<_> = vec![1].into();
        match vec.reserve(core::usize::MAX) {
            Ok(_) => panic!("capacity calculation should overflow"),
            _ => (),
        }
    }

    #[test]
    fn extend_from_slice() {
        let mut vec: Vec<u8> = b"foo".as_ref().into();
        vec.shrink_to_fit();
        vec.reserve(5);
        assert_eq!(8, vec.capacity());
        vec.try_extend_from_slice(b"bar").unwrap();
        assert_eq!(vec, b"foobar".as_ref());
        vec.try_extend_from_slice(b"1").unwrap();
        assert_eq!(vec, b"foobar1".as_ref());
        assert_eq!(8, vec.capacity());
        vec.try_extend_from_slice(b"11").unwrap();
        assert_eq!(16, vec.capacity());
    }

    #[test]
    fn tryvec_extend_from_slice() {
        let mut vec: TryVec<u8> = b"foo".as_ref().try_into().unwrap();
        vec.extend_from_slice(b"bar").unwrap();
        assert_eq!(vec, b"foobar".as_ref());
    }

    #[test]
    fn try_reserve_zst() {
        let mut vec: Vec<()> = Vec::new();
        assert!(FallibleVec::try_reserve(&mut vec, core::usize::MAX).is_ok());
    }
}
