1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! The raw vector type that back-up the [`GenericVec`](crate::GenericVec)

#[cfg(feature = "alloc")]
use std::boxed::Box;
use std::mem::MaybeUninit;

mod array;
#[cfg(any(doc, feature = "alloc"))]
pub(crate) mod heap;
mod slice;

mod capacity;

/// Error on failure to allocate
pub struct AllocError;
/// Result of an allocation
pub type AllocResult = Result<(), AllocError>;

/// A type that can hold `T`s, and potentially
/// reserve space for more `Self::Items`s
///
/// # Safety
///
/// Other safe types rely on this trait being implemented correctly.
/// See the safety requirements on each function
pub unsafe trait Storage: AsRef<[MaybeUninit<Self::Item>]> + AsMut<[MaybeUninit<Self::Item>]> {
    /// The type of item that this storage can contain
    type Item;

    #[doc(hidden)]
    const CONST_CAPACITY: Option<usize> = None;

    /// Reserves space for at least `new_capacity` elements
    ///
    /// # Safety
    ///
    /// After this call successfully ends, the `capacity` must be at least
    /// `new_capacity`
    ///
    /// # Panic/Abort
    ///
    /// Maybe panic or abort if it is impossible to set the `capacity` to at
    /// least `new_capacity`
    fn reserve(&mut self, new_capacity: usize);

    /// Tries to reserve space for at least `new_capacity` elements
    ///
    /// Returns `Ok(())` on success, `Err(AllocError)` if it is impossible to
    /// set the `capacity` to at least `new_capacity`
    ///
    /// # Safety
    ///
    /// If `Ok(())` is returned, the `capacity` must be at least `new_capacity`
    fn try_reserve(&mut self, new_capacity: usize) -> AllocResult;
}

/// A storage that can be initially created with a given capacity
///
/// # Safety
///
/// The storage must have a capacity of at least `capacity` after
/// `StorageWithCapacity::with_capacity` is called.
pub unsafe trait StorageWithCapacity: Storage + Sized {
    /// Creates a new storage with at least the given storage capacity
    fn with_capacity(capacity: usize) -> Self;

    #[doc(hidden)]
    #[allow(non_snake_case)]
    fn __with_capacity__const_capacity_checked(capacity: usize, _old_capacity: Option<usize>) -> Self {
        Self::with_capacity(capacity)
    }
}

unsafe impl<S: ?Sized + Storage> Storage for &mut S {
    type Item = S::Item;

    #[doc(hidden)]
    const CONST_CAPACITY: Option<usize> = S::CONST_CAPACITY;

    #[inline]
    fn reserve(&mut self, new_capacity: usize) { S::reserve(self, new_capacity); }
    #[inline]
    fn try_reserve(&mut self, new_capacity: usize) -> AllocResult { S::try_reserve(self, new_capacity) }
}

/// Wrapper for a [`Box<S>`]. Needed to implement some traits that could not be implemented on Box directly
pub struct BoxStorage<S: ?Sized + Storage>(pub Box<S>);

impl<S: ?Sized + Storage> AsRef<[MaybeUninit<S::Item>]> for BoxStorage<S> {
    fn as_ref(&self) -> &[MaybeUninit<S::Item>] { self.0.as_ref().as_ref() }
}

impl<S: ?Sized + Storage> AsMut<[MaybeUninit<S::Item>]> for BoxStorage<S> {
    fn as_mut(&mut self) -> &mut [MaybeUninit<S::Item>] { self.0.as_mut().as_mut() }
}

#[cfg(any(doc, feature = "alloc"))]
unsafe impl<S: ?Sized + Storage> Storage for BoxStorage<S> {
    type Item = S::Item;

    #[doc(hidden)]
    const CONST_CAPACITY: Option<usize> = S::CONST_CAPACITY;

    #[inline]
    fn reserve(&mut self, new_capacity: usize) { S::reserve(&mut self.0, new_capacity); }
    #[inline]
    fn try_reserve(&mut self, new_capacity: usize) -> AllocResult { S::try_reserve(&mut self.0, new_capacity) }
}

#[cfg(any(doc, feature = "alloc"))]
unsafe impl<S: ?Sized + StorageWithCapacity> StorageWithCapacity for BoxStorage<S> {
    fn with_capacity(capacity: usize) -> Self { Self(Box::new(S::with_capacity(capacity))) }

    #[doc(hidden)]
    #[allow(non_snake_case)]
    fn __with_capacity__const_capacity_checked(capacity: usize, old_capacity: Option<usize>) -> Self {
        Self(Box::new(S::__with_capacity__const_capacity_checked(
            capacity,
            old_capacity,
        )))
    }
}