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(generic_const_exprs)]
31#![feature(const_iter)]
32#![feature(const_convert)]
33#![feature(const_default)]
34
35extern crate alloc;
37
38mod comparisons;
40mod conversions;
41mod errors;
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 },
64 array::from_fn as arrayfn,
65 ptr::copy
66};
67
68use constrangeiter::ConstIntoIterator;
70
71pub use errors::{
73 CapacityExceeded,
74 UnmatchedCapacity
75};
76
77
78pub struct Array<Type, const N: usize> {
84 length: usize,
85 data: [MaybeUninit<Type>; N]
86}
87
88impl<Type, const N: usize> Array<Type, N> {
90 pub const fn len(&self) -> usize {return self.length}
91 pub const fn new() -> Self {return Self::default()}
92 pub const fn is_full(&self) -> bool {return self.length == N}
93 pub const fn repeat<const TIMES: usize>(self) -> Array<Type, {TIMES * N}> where Type: [const] Clone + [const] Destruct, [(); TIMES * N]: {
94 let (length, mut data) = self.into();
95 let mut additional = MaybeUninit::<[Type; TIMES * N]>::uninit().transpose();
96 if TIMES == 0 {for index in (0..length).const_into_iter() {
97 unsafe {data[index].assume_init_drop();};
98 }} else {
99 for index in (0..length).const_into_iter() {
100 additional[index].write(unsafe {data[index].assume_init_read()});
101 }
102 for iteration in (1..TIMES).const_into_iter() {
103 for index in (0..length).const_into_iter() {
104 additional[index + length * iteration].write(unsafe {
105 data[index].assume_init_ref().clone()
106 });
107 }
108 }
109 }
110 return Array::from((length * TIMES, additional));
111 }
112 pub const fn resize<const M: usize>(self) -> Array<Type, M> where Type: [const] Destruct {
113 let (length, mut data) = self.into();
114 let mut additional = MaybeUninit::<[Type; M]>::uninit().transpose();
115 return if M >= length {
116 for index in (0..length).const_into_iter() {
117 additional[index].write(unsafe {data[index].assume_init_read()});
118 }
119 Array::from((length, additional))
120 } else {
121 for index in (0..M).const_into_iter() {
122 additional[index].write(unsafe {data[index].assume_init_read()});
123 }
124 for index in (M..length).const_into_iter() {
125 unsafe {data[index].assume_init_drop()};
126 }
127 Array::from((M, additional))
128 }
129 }
130 pub const fn divide<const AT: usize>(self) -> (
131 Array<Type, AT>,
132 Array<Type, {N - AT}>
133 ) where [(); N - AT]: {
134 let (length, data) = self.into();
135 let (first, second) = unsafe {transmute(data)};
136 return (Array {
137 length: length.min(AT),
138 data: first
139 }, Array {
140 length: length.saturating_sub(AT),
141 data: second
142 })
143 }
144 pub const fn join<const M: usize>(self, other: Array<Type, M>) -> Array<Type, {N + M}> {
145 let (length, data) = self.into();
146 let (slength, sdata) = other.into();
147 let mut together = unsafe {transmute::<_, [MaybeUninit<Type>; N + M]>((data, sdata))};
148 let pointer = together.as_mut_ptr();
149 unsafe {copy(
150 pointer.add(N),
151 pointer.add(length),
152 slength
153 )}
154 return Array {
155 length: length + slength,
156 data: together
157 }
158 }
159 pub const fn push(&mut self, value: Type) -> () {
160 self.push_mut(value);
161 }
162 pub const fn push_mut<'valid>(&'valid mut self, value: Type) -> &'valid mut Type {
163 let reference = self.data[self.length].write(value);
164 self.length += 1;
165 return reference;
166 }
167 pub const fn pop(&mut self) -> Option<Type> {return if self.length == 0 {None} else {
168 self.length -= 1;
169 Some(unsafe {self.data[self.length].assume_init_read()})
170 }}
171 pub const fn pop_if(
172 &mut self,
173 function: impl [const] FnOnce(&mut Type) -> bool + [const] Destruct
174 ) -> Option<Type> {return if self.length == 0 {None} else {
175 let last = &mut self.data[self.length - 1];
176 if function(unsafe {last.assume_init_mut()}) {
177 self.length -= 1;
178 Some(unsafe {replace(
179 last,
180 MaybeUninit::uninit()
181 ).assume_init()})
182 } else {None}
183 }}
184 pub const fn clear(&mut self) -> () where Type: [const] Destruct {self.truncate(0)}
185 pub const fn truncate(&mut self, length: usize) -> () where Type: [const] Destruct {
186 for index in (length..self.length).const_into_iter() {
187 unsafe {self.data.get_unchecked_mut(index).assume_init_drop()};
188 }
189 self.length = length;
190 }
191 pub const fn insert(&mut self, index: usize, value: Type) -> () {
192 self.insert_mut(index, value);
193 }
194 pub const fn insert_mut<'valid>(
195 &'valid mut self,
196 index: usize,
197 value: Type
198 ) -> &'valid mut Type {
199 assert!(index <= self.length, "tried to insert out of bounds");
200 assert!(self.length != N, "array capacity exceeded");
201 let pointer = unsafe {self.data.as_mut_ptr().add(index)};
202 unsafe {copy(
203 pointer,
204 pointer.add(1),
205 self.length - index
206 )};
207 let reference = unsafe {self.data.get_unchecked_mut(index).write(value)};
208 self.length += 1;
209 return reference;
210 }
211 pub const fn remove(&mut self, index: usize) -> Type {
212 assert!(index < self.length, "tried to remove out of bounds");
213 let value = unsafe {self.data.get_unchecked(index).assume_init_read()};
214 let pointer = unsafe {self.data.as_mut_ptr().add(index)};
215 unsafe {copy(
216 pointer.add(1),
217 pointer,
218 self.length - index - 1
219 )};
220 self.length -= 1;
221 return value;
222 }
223 pub const fn swap_remove(&mut self, index: usize) -> Type {
224 assert!(index < self.length - 1, "tried to remove out of bounds");
225 let value = unsafe {self.data[index].assume_init_read()};
226 self.data.swap(index, self.length - 1);
227 self.length -= 1;
228 return value;
229 }
230 pub const fn retain(
231 &mut self,
232 mut closure: impl [const] FnMut(&mut Type) -> bool + [const] Destruct
233 ) -> () where Type: [const] Destruct {
234 let mut offset = 0;
235 for index in (0..self.length).const_into_iter() {
236 let mut item = unsafe {self.data[index].assume_init_read()};
237 match (closure(&mut item), offset == 0) {
238 (true, true) => forget(item),
239 (true, false) => {self.data[index - offset].write(item);},
240 (false, _) => {
241 drop(item);
242 offset += 1;
243 }
244 }
245 }
246 self.length -= offset;
247 }
248 pub const fn dedup(
249 &mut self
250 ) -> () where Type: [const] PartialEq<Type> + [const] Destruct {self.dedup_by_key_with(
251 const |element| element as *const Type,
252 const |first, second| unsafe {first.as_ref().unwrap() == second.as_ref().unwrap()}
253 )}
254 pub const fn dedup_with(
255 &mut self,
256 mut decider: impl [const] FnMut(&mut Type, &mut Type) -> bool + [const] Destruct
257 ) -> () where Type: [const] Destruct {self.dedup_by_key_with(
258 const |element| element as *mut Type,
259 const |first, second| unsafe {decider(
260 first.as_mut().unwrap(),
261 second.as_mut().unwrap()
262 )}
263 )}
264 pub const fn dedup_by_key<
265 'valid,
266 Key: 'valid + [const] PartialEq<Key> + [const] Destruct
267 >(
268 &'valid mut self,
269 transformation: impl for<'any> [const] FnMut(&'any mut Type) -> Key + [const] Destruct
270 ) -> () where Type: [const] Destruct {self.dedup_by_key_with(
271 transformation,
272 const |first, second| first == second
273 )}
274 pub const fn dedup_by_key_with<'valid, Key: 'valid + [const] Destruct>(
275 &'valid mut self,
276 mut transformation: impl for<'any> [const] FnMut(&'any mut Type) -> Key + [const] Destruct,
277 mut decider: impl [const] FnMut(&mut Key, &mut Key) -> bool + [const] Destruct
278 ) -> () where Type: [const] Destruct {
279 if self.length == 0 {return}
280 let mut offset = 0;
281 let mut previous = transformation(unsafe {self.data[0].assume_init_mut()});
282 for index in (1..self.length).const_into_iter() {
283 let current = unsafe {self.data[index].assume_init_mut()};
284 let mut key = transformation(current);
285 if decider(&mut previous, &mut key) {
286 unsafe {(current as *mut Type).drop_in_place()};
287 drop(key);
288 offset += 1;
289 } else {
290 previous = key;
291 if offset != 0 {
292 let value = unsafe {(current as *mut Type).read()};
293 self.data[index - offset].write(value);
294 }
295 }
296 }
297 self.length -= offset;
298 }
299 pub const fn drain(
300 &mut self,
301 range: impl [const] RangeBounds<usize> + [const] Destruct
302 ) -> Self {
303 let start = match range.start_bound() {
304 Bound::Excluded(_) => unreachable!(),
305 Bound::Included(bound) => {
306 assert!(*bound < self.length);
307 *bound
308 },
309 Bound::Unbounded => 0
310 };
311 let end = match range.end_bound() {
312 Bound::Excluded(bound) => {
313 assert!(*bound <= self.length);
314 *bound
315 },
316 Bound::Included(bound) => {
317 assert!(*bound < self.length);
318 *bound + 1
319 },
320 Bound::Unbounded => self.length
321 };
322 let mut additional = MaybeUninit::<[Type; N]>::uninit().transpose();
323 let array = match end - start {
324 0 => Array {
325 length: 0,
326 data: additional
327 },
328 1 => {
329 additional[0].write(self.remove(start));
330 Array {
331 length: 1,
332 data: additional
333 }
334 },
335 amount => {
336 for index in (start..end).const_into_iter() {
337 additional[index - start].write(unsafe {
338 self.data[index].assume_init_read()
339 });
340 }
341 for index in (end..self.length).const_into_iter() {
342 self.data[index - end + start].write(unsafe {
343 self.data[index].assume_init_read()
344 });
345 }
346 self.length -= end - start;
347 Array {
348 length: amount,
349 data: additional
350 }
351 }
352 };
353 return array;
354 }
355}
356
357const impl<Type: [const] Destruct, const N: usize> Drop for Array<Type, N> {
359 fn drop(&mut self) {self.clear()}
360}
361
362impl<Type: Debug, const N: usize> Debug for Array<Type, N> {
364 fn fmt(&self, formatter: &mut Formatter<'_>) -> Format {
365 return Debug::fmt(self.as_ref(), formatter);
366 }
367}
368
369impl<Type, const N: usize> Extend<Type> for Array<Type, N> {
371 fn extend<T: IntoIterator<Item = Type>>(&mut self, iter: T) {
372 iter.into_iter().for_each(|item| self.push(item));
373 }
374}
375
376const impl<Type: [const] Clone, const N: usize> Clone for Array<Type, N> {
378 fn clone(&self) -> Self {return Array {
379 length: self.length,
380 data: arrayfn(const |index| if index >= self.length {MaybeUninit::uninit()} else {
381 MaybeUninit::new(unsafe {self.data[index].assume_init_ref().clone()})
382 })
383 }}
384}
385
386const impl<Type, const N: usize> Default for Array<Type, N> {
388 fn default() -> Self {return Self {
389 data: MaybeUninit::uninit().transpose(),
390 length: 0
391 }}
392}