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| element as *const Type,
245        const |first, second| unsafe {first.as_ref().unwrap() == second.as_ref().unwrap()}
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| element as *mut Type, 
252        const |first, second| unsafe {decider(
253            first.as_mut().unwrap(), 
254            second.as_mut().unwrap()
255        )}
256    )}
257    pub const fn dedup_by_key<
258        'valid, 
259        Key: 'valid + [const] PartialEq<Key> + [const] Destruct
260    >(
261        &'valid mut self,
262        transformation: impl for<'any> [const] FnMut(&'any mut Type) -> Key + [const] Destruct
263    ) -> () where Type: [const] Destruct {self.dedup_by_key_with(
264        transformation, 
265        const |first, second| first == second
266    )}
267    pub const fn dedup_by_key_with<'valid, Key: 'valid + [const] Destruct>(
268        &'valid mut self, 
269        mut transformation: impl for<'any> [const] FnMut(&'any mut Type) -> Key + [const] Destruct,
270        mut decider: impl [const] FnMut(&mut Key, &mut Key) -> bool + [const] Destruct
271    ) -> () where Type: [const] Destruct {
272        if self.length == 0 {return}
273        let mut offset = 0;
274        let mut previouskey = transformation(unsafe {self.data[0].assume_init_mut()});
275        for index in (1..self.length).const_into_iter() {
276            let current = unsafe {self.data[index].assume_init_mut()};
277            let mut currentkey = transformation(current);
278            if decider(&mut previouskey, &mut currentkey) {
279                unsafe {(current as *mut Type).drop_in_place()};
280                drop(currentkey);
281                offset += 1;
282            } else {
283                previouskey = currentkey;
284                if offset != 0 {
285                    let value = unsafe {(current as *mut Type).read()};
286                    self.data[index - offset].write(value);
287                }
288            }
289        }
290        self.length -= offset;
291    }
292    pub const fn drain(
293        &mut self, 
294        range: impl [const] RangeBounds<usize> + [const] Destruct
295    ) -> Self {
296        let start = match range.start_bound() {
297            Bound::Excluded(_) => unreachable!(),
298            Bound::Included(bound) => {
299                assert!(*bound < self.length);
300                *bound
301            },
302            Bound::Unbounded => 0
303        };
304        let end = match range.end_bound() {
305            Bound::Excluded(bound) => {
306                assert!(*bound <= self.length);
307                *bound
308            },
309            Bound::Included(bound) => {
310                assert!(*bound < self.length);
311                *bound + 1
312            },
313            Bound::Unbounded => self.length
314        };
315        let mut additional = MaybeUninit::<[Type; N]>::uninit().transpose();
316        let array = match end - start {
317            0 => Array {
318                length: 0,
319                data: additional
320            },
321            1 => {
322                additional[0].write(self.remove(start));
323                Array {
324                    length: 1,
325                    data: additional
326                }
327            },
328            amount => {
329                for index in (start..end).const_into_iter() {
330                    additional[index - start].write(unsafe {
331                        self.data[index].assume_init_read()
332                    });
333                }
334                for index in (end..self.length).const_into_iter() {
335                    self.data[index - end + start].write(unsafe {
336                        self.data[index].assume_init_read()
337                    });
338                }
339                self.length -= end - start;
340                Array {
341                    length: amount,
342                    data: additional
343                }
344            }
345        };
346        return array;
347    }
348}
349
350//> ARRAY -> DROP
351const impl<Type: [const] Destruct, const N: usize> Drop for Array<Type, N> {
352    fn drop(&mut self) {self.clear()}
353}
354
355//> ARRAY -> DEBUG
356impl<Type: Debug, const N: usize> Debug for Array<Type, N> {
357    fn fmt(&self, formatter: &mut Formatter<'_>) -> Format {
358        return Debug::fmt(self.as_ref(), formatter);
359    }
360}
361
362//> ARRAY -> EXTEND
363impl<Type, const N: usize> Extend<Type> for Array<Type, N> {
364    fn extend<T: IntoIterator<Item = Type>>(&mut self, iter: T) {
365        iter.into_iter().for_each(|item| self.push(item));
366    }
367}
368
369//> ARRAY -> CLONE
370const impl<Type: [const] Clone, const N: usize> Clone for Array<Type, N> {
371    fn clone(&self) -> Self {return Array {
372        length: self.length,
373        data: arrayfn(const |index| if index >= self.length {MaybeUninit::uninit()} else {
374            MaybeUninit::new(unsafe {self.data[index].assume_init_ref().clone()})
375        })
376    }}
377}
378
379//> ARRAY -> DEFAULT
380const impl<Type, const N: usize> Default for Array<Type, N> {
381    fn default() -> Self {return Self {
382        data: MaybeUninit::uninit().transpose(),
383        length: 0
384    }}
385}