Skip to main content

stack_array/
mod.rs

1//^
2//^ HEAD
3//^
4
5//> HEAD -> NO_STD
6#![no_std]
7
8//> HEAD -> DOCS
9#![doc = include_str!("README.md")]
10
11//> HEAD -> LINTS
12#![allow(incomplete_features)]
13
14//> HEAD -> FEATURES
15#![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
35//> HEAD -> CRATES
36extern crate alloc;
37
38//> HEAD -> MODULES
39mod comparisons;
40mod conversions;
41mod errors;
42mod iterators;
43mod references;
44
45//> HEAD -> CORE
46use 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
68//> HEAD -> CONSTRANGEITER
69use constrangeiter::ConstIntoIterator;
70
71//> HEAD -> ERRORS
72pub use errors::{
73    CapacityExceeded,
74    UnmatchedCapacity
75};
76
77
78//^
79//^ ARRAY
80//^
81
82//> ARRAY -> STRUCT
83pub struct Array<Type, const N: usize> {
84    length: usize,
85    data: [MaybeUninit<Type>; N]
86}
87
88//> ARRAY -> IMPLEMENTATION
89impl<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
357//> ARRAY -> DROP
358const impl<Type: [const] Destruct, const N: usize> Drop for Array<Type, N> {
359    fn drop(&mut self) {self.clear()}
360}
361
362//> ARRAY -> DEBUG
363impl<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
369//> ARRAY -> EXTEND
370impl<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
376//> ARRAY -> CLONE
377const 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
386//> ARRAY -> DEFAULT
387const 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}