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