summaryrefslogtreecommitdiff
path: root/ecs/src/util/array_vec.rs
blob: 648c97646cd16df99cbfb443c07463d7d5baa40e (plain)
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
use std::mem::{transmute, MaybeUninit};
use std::ops::{Deref, DerefMut};

#[derive(Debug)]
pub struct ArrayVec<Item, const CAPACITY: usize>
{
    items: [MaybeUninit<Item>; CAPACITY],
    len: usize,
}

impl<Item, const CAPACITY: usize> ArrayVec<Item, CAPACITY>
{
    pub fn new() -> Self
    {
        Self::default()
    }

    #[inline]
    #[must_use]
    pub fn len(&self) -> usize
    {
        self.len
    }

    pub fn push(&mut self, item: Item)
    {
        assert!(self.len < CAPACITY);

        self.items[self.len].write(item);

        self.len += 1;
    }

    pub fn insert(&mut self, index: usize, item: Item)
    {
        assert!(index <= self.len);
        assert!(self.len < CAPACITY);

        if index == self.len {
            self.push(item);
            return;
        }

        unsafe {
            std::ptr::copy(
                &self.items[index],
                &mut self.items[index + 1],
                self.len - index,
            );
        }

        self.items[index].write(item);

        self.len += 1;
    }
}

impl<Item, const CAPACITY: usize> Extend<Item> for ArrayVec<Item, CAPACITY>
{
    fn extend<IntoIter: IntoIterator<Item = Item>>(&mut self, iter: IntoIter)
    {
        for item in iter {
            self.push(item);
        }
    }
}

impl<Item, const CAPACITY: usize> AsRef<[Item]> for ArrayVec<Item, CAPACITY>
{
    fn as_ref(&self) -> &[Item]
    {
        unsafe { transmute::<&[MaybeUninit<Item>], &[Item]>(&self.items[..self.len]) }
    }
}

impl<Item, const CAPACITY: usize> AsMut<[Item]> for ArrayVec<Item, CAPACITY>
{
    fn as_mut(&mut self) -> &mut [Item]
    {
        unsafe {
            transmute::<&mut [MaybeUninit<Item>], &mut [Item]>(
                &mut self.items[..self.len],
            )
        }
    }
}

impl<Item, const CAPACITY: usize> Deref for ArrayVec<Item, CAPACITY>
{
    type Target = [Item];

    fn deref(&self) -> &Self::Target
    {
        self.as_ref()
    }
}

impl<Item, const CAPACITY: usize> DerefMut for ArrayVec<Item, CAPACITY>
{
    fn deref_mut(&mut self) -> &mut Self::Target
    {
        self.as_mut()
    }
}

impl<Item, const CAPACITY: usize> Default for ArrayVec<Item, CAPACITY>
{
    fn default() -> Self
    {
        Self {
            items: [const { MaybeUninit::uninit() }; CAPACITY],
            len: 0,
        }
    }
}