1use core::marker::PhantomData;
3
4use crate::{id::Id, slab::SlabItem};
5
6#[derive(Clone, Copy)]
8pub struct ArrayIter<T> {
9 array: Array<T>,
10 index: usize,
11}
12
13impl<T: SlabItem> Iterator for ArrayIter<T> {
14 type Item = Id<T>;
15
16 fn next(&mut self) -> Option<Self::Item> {
17 if self.index >= self.array.len() {
18 None
19 } else {
20 let id = self.array.at(self.index);
21 self.index += 1;
22 Some(id)
23 }
24 }
25}
26
27#[repr(C)]
41pub struct Array<T> {
42 pub index: u32,
44 pub len: u32,
46 _phantom: PhantomData<T>,
47}
48
49impl<T> Clone for Array<T> {
50 fn clone(&self) -> Self {
51 *self
52 }
53}
54
55impl<T> Copy for Array<T> {}
56
57impl<T> From<Id<T>> for Array<T> {
59 fn from(id: Id<T>) -> Self {
60 Self {
61 index: id.inner(),
62 len: 1,
63 _phantom: PhantomData,
64 }
65 }
66}
67
68impl<T> core::fmt::Debug for Array<T> {
69 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70 if self.is_null() {
71 f.write_fmt(core::format_args!(
72 "Array<{}>(null)",
73 core::any::type_name::<T>()
74 ))
75 } else {
76 f.write_fmt(core::format_args!(
77 "Array<{}>({}, {})",
78 core::any::type_name::<T>(),
79 self.index,
80 self.len
81 ))
82 }
83 }
84}
85
86impl<T> PartialEq for Array<T> {
87 fn eq(&self, other: &Self) -> bool {
88 self.index == other.index && self.len == other.len
89 }
90}
91
92impl<T: SlabItem> SlabItem for Array<T> {
93 const SLAB_SIZE: usize = 2;
94
95 fn write_slab(&self, index: usize, slab: &mut [u32]) -> usize {
96 let index = self.index.write_slab(index, slab);
97 self.len.write_slab(index, slab)
98 }
99
100 fn read_slab(index: usize, slab: &[u32]) -> Self {
101 let start = u32::read_slab(index, slab);
102 let len = u32::read_slab(index + 1, slab);
103 Array::new(start, len)
104 }
105}
106
107impl<T: SlabItem> Default for Array<T> {
108 fn default() -> Self {
109 Array::NONE
110 }
111}
112
113impl<T> Array<T> {
114 pub const NONE: Self = Array::new(u32::MAX, 0);
115
116 pub const fn new(index: u32, len: u32) -> Self {
117 Self {
118 index,
119 len,
120 _phantom: PhantomData,
121 }
122 }
123
124 pub fn len(&self) -> usize {
125 self.len as usize
126 }
127
128 pub fn is_empty(&self) -> bool {
129 self.len == 0
130 }
131
132 pub fn is_null(&self) -> bool {
133 self.index == u32::MAX
134 }
135
136 pub fn contains_index(&self, index: usize) -> bool {
137 index >= self.index as usize && index < (self.index + self.len) as usize
138 }
139
140 pub fn at(&self, index: usize) -> Id<T>
141 where
142 T: SlabItem,
143 {
144 if index >= self.len() {
145 Id::NONE
146 } else {
147 Id::new(self.index + (T::SLAB_SIZE * index) as u32)
148 }
149 }
150
151 pub fn starting_index(&self) -> usize {
152 self.index as usize
153 }
154
155 pub fn iter(&self) -> ArrayIter<T> {
156 ArrayIter {
157 array: *self,
158 index: 0,
159 }
160 }
161
162 pub fn into_u32_array(self) -> Array<u32>
164 where
165 T: SlabItem,
166 {
167 Array {
168 index: self.index,
169 len: self.len * T::SLAB_SIZE as u32,
170 _phantom: PhantomData,
171 }
172 }
173
174 #[cfg(not(target_arch = "spirv"))]
175 pub fn sub_slab<'a>(&'a self, slab: &'a [u32]) -> &'a [u32]
177 where
178 T: SlabItem,
179 {
180 let arr = self.into_u32_array();
181 &slab[arr.index as usize..(arr.index + arr.len) as usize]
182 }
183}
184
185impl Array<u32> {
186 pub fn union(&mut self, other: &Array<u32>) {
187 let start = self.index.min(other.index);
188 let end = (self.index + self.len).max(other.index + other.len);
189 self.index = start;
190 self.len = end - start;
191 }
192}