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
use crate::raw::{Storage, StorageWithCapacity};
use core::marker::PhantomData;

/// A storage that can hold zero sized types
pub struct ZeroSized<T>(PhantomData<T>);

impl<T> Default for ZeroSized<T> {
    #[inline]
    fn default() -> Self { Self::NEW }
}

impl<T> Copy for ZeroSized<T> {}
impl<T> Clone for ZeroSized<T> {
    #[inline]
    fn clone(&self) -> Self { Self::NEW }
}

impl<T> ZeroSized<T> {
    /// Create a new zero-sized allocator, can only be used with zero-sized types
    ///
    /// ```rust
    /// # use generic_vec::raw::ZeroSized;
    /// let _ = ZeroSized::<[i32; 0]>::NEW;
    /// ```
    ///
    /// ```compile_fail
    /// # use generic_vec::raw::ZeroSized;
    /// let _ = ZeroSized::<u8>::NEW;
    /// ```
    pub const NEW: Self = ZeroSized([PhantomData][core::mem::size_of::<T>()]);

    /// Try to create a new zero-sized allocator, will be `None`
    /// if the type is not zero sized
    ///
    /// ```rust
    /// # use generic_vec::raw::ZeroSized;
    /// assert!(ZeroSized::<[i32; 0]>::TRY_NEW.is_some());
    /// assert!(ZeroSized::<u8>::TRY_NEW.is_none());
    /// ```
    pub const TRY_NEW: Option<Self> = [None, Some(ZeroSized(PhantomData))][(core::mem::size_of::<T>() == 0) as usize];

    const DANGLING: *mut T = core::mem::align_of::<T>() as *mut T;
}

unsafe impl<T> Storage<T> for ZeroSized<T> {
    const CONST_CAPACITY: Option<usize> = Some(usize::MAX);
    const IS_ALIGNED: bool = true;

    #[inline]
    fn as_ptr(&self) -> *const T { Self::DANGLING }
    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T { Self::DANGLING }

    #[inline]
    fn reserve(&mut self, _: usize) {}
    #[inline]
    fn try_reserve(&mut self, _: usize) -> bool { true }
    #[inline]
    fn capacity(&self) -> usize { usize::MAX }
}

unsafe impl<T> StorageWithCapacity<T> for ZeroSized<T> {
    #[inline]
    fn with_capacity(_: usize) -> Self { Self::NEW }
}