1#![no_std]
7
8#![doc = include_str!("README.md")]
10
11#![allow(incomplete_features)]
13
14#![feature(const_cmp)]
16#![feature(const_destruct)]
17#![feature(const_drop_in_place)]
18#![feature(const_array)]
19#![feature(transmute_neo)]
20#![feature(const_index)]
21#![feature(const_range)]
22#![feature(maybe_uninit_uninit_array_transpose)]
23#![feature(const_closures)]
24#![feature(const_trait_impl)]
25#![feature(box_vec_non_null)]
26#![feature(trusted_len)]
27#![feature(const_clone)]
28#![feature(new_range)]
29#![feature(const_slice_make_iter)]
30#![feature(const_ops)]
31#![feature(generic_const_exprs)]
32#![feature(const_iter)]
33#![feature(const_convert)]
34#![feature(const_default)]
35
36extern crate alloc;
38
39mod comparisons;
41mod conversions;
42mod iterators;
43mod references;
44
45use core::{
47 fmt::{
48 Debug,
49 Formatter,
50 Result as Format
51 },
52 marker::Destruct,
53 mem::{
54 MaybeUninit,
55 forget,
56 transmute_neo as transmute,
57 replace
58 },
59 ops::{
60 Bound,
61 Drop,
62 RangeBounds,
63 SubAssign
64 },
65 array::from_fn as arrayfn,
66 ptr::copy
67};
68
69use constrangeiter::ConstIntoIterator;
71
72
73pub struct Array<Type, const N: usize> {
79 length: usize,
80 data: [MaybeUninit<Type>; N]
81}
82
83impl<Type, const N: usize> Array<Type, N> {
85 pub const fn len(&self) -> usize {return self.length}
86 pub const fn new() -> Self {return Self::default()}
87 pub const fn is_full(&self) -> bool {return self.length == N}
88 pub const fn repeat<const TIMES: usize>(self) -> Array<Type, {TIMES * N}> where Type: [const] Clone + [const] Destruct, [(); TIMES * N]: {
89 let (length, mut data) = self.into();
90 let mut additional = MaybeUninit::<[Type; TIMES * N]>::uninit().transpose();
91 if TIMES == 0 {for index in (0..length).const_into_iter() {
92 unsafe {data[index].assume_init_drop();};
93 }} else {
94 for index in (0..length).const_into_iter() {
95 additional[index].write(unsafe {data[index].assume_init_read()});
96 }
97 for iteration in (1..TIMES).const_into_iter() {
98 for index in (0..length).const_into_iter() {
99 additional[index + length * iteration].write(unsafe {
100 data[index].assume_init_ref().clone()
101 });
102 }
103 }
104 }
105 return Array::from((length * TIMES, additional));
106 }
107 pub const fn resize<const M: usize>(self) -> Array<Type, M> where Type: [const] Destruct {
108 let (length, mut data) = self.into();
109 let mut additional = MaybeUninit::<[Type; M]>::uninit().transpose();
110 return if M >= length {
111 for index in (0..length).const_into_iter() {
112 additional[index].write(unsafe {data[index].assume_init_read()});
113 }
114 Array::from((length, additional))
115 } else {
116 for index in (0..M).const_into_iter() {
117 additional[index].write(unsafe {data[index].assume_init_read()});
118 }
119 for index in (M..length).const_into_iter() {
120 unsafe {data[index].assume_init_drop()};
121 }
122 Array::from((M, additional))
123 }
124 }
125 pub const fn divide<const AT: usize>(self) -> (
126 Array<Type, AT>,
127 Array<Type, {N - AT}>
128 ) where [(); N - AT]: {
129 let (length, data) = self.into();
130 let (first, second) = unsafe {transmute(data)};
131 return (Array {
132 length: length.min(AT),
133 data: first
134 }, Array {
135 length: length.saturating_sub(AT),
136 data: second
137 })
138 }
139 pub const fn join<const M: usize>(self, other: Array<Type, M>) -> Array<Type, {N + M}> {
140 let (length, data) = self.into();
141 let (slength, sdata) = other.into();
142 let mut together = unsafe {transmute::<_, [MaybeUninit<Type>; N + M]>((data, sdata))};
143 let pointer = together.as_mut_ptr();
144 unsafe {copy(
145 pointer.add(N),
146 pointer.add(length),
147 slength
148 )}
149 return Array {
150 length: length + slength,
151 data: together
152 }
153 }
154 pub const fn push(&mut self, value: Type) -> () {
155 self.push_mut(value);
156 }
157 pub const fn push_mut<'valid>(&'valid mut self, value: Type) -> &'valid mut Type {
158 let reference = self.data[self.length].write(value);
159 self.length += 1;
160 return reference;
161 }
162 pub const fn pop(&mut self) -> Option<Type> {return if self.length == 0 {None} else {
163 self.length -= 1;
164 Some(unsafe {self.data[self.length].assume_init_read()})
165 }}
166 pub const fn pop_if(
167 &mut self,
168 function: impl [const] FnOnce(&mut Type) -> bool + [const] Destruct
169 ) -> Option<Type> {return if self.length == 0 {None} else {
170 let last = &mut self.data[self.length - 1];
171 if function(unsafe {last.assume_init_mut()}) {
172 self.length -= 1;
173 Some(unsafe {replace(
174 last,
175 MaybeUninit::uninit()
176 ).assume_init()})
177 } else {None}
178 }}
179 pub const fn clear(&mut self) -> () where Type: [const] Destruct {self.truncate(0)}
180 pub const fn truncate(&mut self, length: usize) -> () where Type: [const] Destruct {
181 for index in (length..self.length).const_into_iter() {
182 unsafe {self.data.get_unchecked_mut(index).assume_init_drop()};
183 }
184 self.length = length;
185 }
186 pub const fn insert(&mut self, index: usize, value: Type) -> () {
187 self.insert_mut(index, value);
188 }
189 pub const fn insert_mut<'valid>(
190 &'valid mut self,
191 index: usize,
192 value: Type
193 ) -> &'valid mut Type {
194 assert!(index <= self.length, "tried to insert out of bounds");
195 assert!(self.length != N, "array capacity exceeded");
196 let pointer = unsafe {self.data.as_mut_ptr().add(index)};
197 unsafe {copy(
198 pointer,
199 pointer.add(1),
200 self.length - index
201 )};
202 let reference = unsafe {self.data.get_unchecked_mut(index).write(value)};
203 self.length += 1;
204 return reference;
205 }
206 pub const fn remove(&mut self, index: usize) -> Type {
207 assert!(index < self.length, "tried to remove out of bounds");
208 let value = unsafe {self.data.get_unchecked(index).assume_init_read()};
209 let pointer = unsafe {self.data.as_mut_ptr().add(index)};
210 unsafe {copy(
211 pointer.add(1),
212 pointer,
213 self.length - index - 1
214 )};
215 self.length -= 1;
216 return value;
217 }
218 pub const fn swap_remove(&mut self, index: usize) -> Type {
219 assert!(index < self.length - 1, "tried to remove out of bounds");
220 let value = unsafe {self.data[index].assume_init_read()};
221 self.data.swap(index, self.length - 1);
222 self.length -= 1;
223 return value;
224 }
225 pub const fn retain(
226 &mut self,
227 mut closure: impl [const] FnMut(&mut Type) -> bool + [const] Destruct
228 ) -> () where Type: [const] Destruct {
229 let mut offset = 0;
230 for index in (0..self.length).const_into_iter() {
231 let mut item = unsafe {self.data[index].assume_init_read()};
232 match (closure(&mut item), offset == 0) {
233 (true, true) => forget(item),
234 (true, false) => {self.data[index - offset].write(item);},
235 (false, _) => {
236 drop(item);
237 offset += 1;
238 }
239 }
240 }
241 self.length -= offset;
242 }
243 pub const fn dedup(
244 &mut self
245 ) -> () where Type: [const] PartialEq<Type> + [const] Destruct {
246 self.dedup_by(const |first, second| (first as &Type).eq(second as &Type));
247 }
248 pub const fn dedup_by(
249 &mut self,
250 mut decider: impl [const] FnMut(&mut Type, &mut Type) -> bool + [const] Destruct
251 ) -> () where Type: [const] Destruct {
252 if self.length < 2 {return}
253 let mut offset = 0;
254 let mut first = None;
255 for index in (0..self.length).const_into_iter() {
256 let mut second = unsafe {self.data[index].assume_init_read()};
257 if first.is_none() {
258 first = Some(second);
259 continue;
260 }
261 if decider(first.as_mut().unwrap(), &mut second) {
262 drop(second);
263 offset += 1;
264 } else {
265 if offset == 0 {
266 forget(first.replace(second).unwrap());
267 } else {
268 let pointer = self.data[index - offset].write(second) as *mut Type;
269 forget(first.replace(
270 unsafe {pointer.read()}
271 ).unwrap());
272 }
273 }
274 }
275 self.length.sub_assign(offset);
276 }
277 pub const fn dedup_by_key<Key: [const] PartialEq<Key> + [const] Destruct>(
278 &mut self,
279 mut transformation: impl [const] FnMut(&mut Type) -> Key + [const] Destruct
280 ) -> () where Type: [const] Destruct {
281 self.dedup_by(const |first, second| transformation(first) == transformation(second));
282 }
283 pub const fn drain(
284 &mut self,
285 range: impl [const] RangeBounds<usize> + [const] Destruct
286 ) -> Self {
287 let start = match range.start_bound() {
288 Bound::Excluded(_) => unreachable!(),
289 Bound::Included(bound) => { assert!(*bound < self.length);
291 *bound
292 },
293 Bound::Unbounded => 0
294 };
295 let end = match range.end_bound() {
296 Bound::Excluded(bound) => { assert!(*bound <= self.length);
298 *bound
299 },
300 Bound::Included(bound) => { assert!(*bound < self.length);
302 *bound + 1
303 },
304 Bound::Unbounded => self.length
305 };
306 let mut additional = MaybeUninit::<[Type; N]>::uninit().transpose();
307 let array = match end - start {
308 0 => Array {
309 length: 0,
310 data: additional
311 },
312 1 => {
313 additional[0].write(self.remove(start));
314 Array {
315 length: 1,
316 data: additional
317 }
318 },
319 amount => {
320 for index in (start..end).const_into_iter() {
321 additional[index - start].write(unsafe {
322 self.data[index].assume_init_read()
323 });
324 }
325 for index in (end..self.length).const_into_iter() {
326 self.data[index - end + start].write(unsafe {
327 self.data[index].assume_init_read()
328 });
329 }
330 self.length -= end - start;
331 Array {
332 length: amount,
333 data: additional
334 }
335 }
336 };
337 return array;
338 }
339}
340
341const impl<Type: [const] Destruct, const N: usize> Drop for Array<Type, N> {
343 fn drop(&mut self) {self.clear()}
344}
345
346impl<Type: Debug, const N: usize> Debug for Array<Type, N> {
348 fn fmt(&self, formatter: &mut Formatter<'_>) -> Format {
349 return Debug::fmt(self.as_ref(), formatter);
350 }
351}
352
353impl<Type, const N: usize> Extend<Type> for Array<Type, N> {
355 fn extend<T: IntoIterator<Item = Type>>(&mut self, iter: T) {
356 iter.into_iter().for_each(|item| self.push(item));
357 }
358}
359
360const impl<Type: [const] Clone, const N: usize> Clone for Array<Type, N> {
362 fn clone(&self) -> Self {return Array {
363 length: self.length,
364 data: arrayfn(const |index| if index >= self.length {MaybeUninit::uninit()} else {
365 MaybeUninit::new(unsafe {self.data[index].assume_init_ref().clone()})
366 })
367 }}
368}
369
370const impl<Type, const N: usize> Default for Array<Type, N> {
372 fn default() -> Self {return Self {
373 data: MaybeUninit::uninit().transpose(),
374 length: 0
375 }}
376}