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(const_ops)]
31#![feature(generic_const_exprs)]
32#![feature(const_iter)]
33#![feature(const_convert)]
34#![feature(const_default)]
35
36//> HEAD -> CRATES
37extern crate alloc;
38
39//> HEAD -> MODULES
40mod comparisons;
41mod conversions;
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        SubAssign
64    }, 
65    array::from_fn as arrayfn,
66    ptr::copy
67};
68
69//> HEAD -> CONSTRANGEITER
70use constrangeiter::ConstIntoIterator;
71
72
73//^
74//^ ARRAY
75//^
76
77//> ARRAY -> STRUCT
78pub struct Array<Type, const N: usize> {
79    length: usize,
80    data: [MaybeUninit<Type>; N]
81}
82
83//> ARRAY -> IMPLEMENTATION
84impl<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) => { // 2.. => 2
290                assert!(*bound < self.length);
291                *bound
292            },
293            Bound::Unbounded => 0
294        };
295        let end = match range.end_bound() {
296            Bound::Excluded(bound) => { // ..2 => 2
297                assert!(*bound <= self.length);
298                *bound
299            },
300            Bound::Included(bound) => { // ..=2 => 3
301                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
341//> ARRAY -> DROP
342const impl<Type: [const] Destruct, const N: usize> Drop for Array<Type, N> {
343    fn drop(&mut self) {self.clear()}
344}
345
346//> ARRAY -> DEBUG
347impl<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
353//> ARRAY -> EXTEND
354impl<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
360//> ARRAY -> CLONE
361const 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
370//> ARRAY -> DEFAULT
371const 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}