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 push(&mut self, value: Type) -> () {
140        self.push_mut(value);
141    }
142    pub const fn push_mut<'valid>(&'valid mut self, value: Type) -> &'valid mut Type {
143        let reference = self.data[self.length].write(value);
144        self.length += 1;
145        return reference;
146    }
147    pub const fn pop(&mut self) -> Option<Type> {return if self.length == 0 {None} else {
148        self.length -= 1;
149        Some(unsafe {self.data[self.length].assume_init_read()})
150    }}
151    pub const fn pop_if(
152        &mut self, 
153        function: impl [const] FnOnce(&mut Type) -> bool + [const] Destruct
154    ) -> Option<Type> {return if self.length == 0 {None} else {
155        let last = &mut self.data[self.length - 1];
156        if function(unsafe {last.assume_init_mut()}) {
157            self.length -= 1;
158            Some(unsafe {replace(
159                last,
160                MaybeUninit::uninit()
161            ).assume_init()})
162        } else {None}
163    }}
164    pub const fn clear(&mut self) -> () where Type: [const] Destruct {self.truncate(0)}
165    pub const fn truncate(&mut self, length: usize) -> () where Type: [const] Destruct {
166        for index in (length..self.length).const_into_iter() {
167            unsafe {self.data.get_unchecked_mut(index).assume_init_drop()};
168        }
169        self.length = length;
170    }
171    pub const fn insert(&mut self, index: usize, value: Type) -> () {
172        self.insert_mut(index, value);
173    }
174    pub const fn insert_mut<'valid>(
175        &'valid mut self, 
176        index: usize, 
177        value: Type
178    ) -> &'valid mut Type {
179        assert!(index <= self.length, "tried to insert out of bounds");
180        assert!(self.length != N, "array capacity exceeded");
181        let pointer = unsafe {self.data.as_mut_ptr().add(index)};
182        unsafe {copy(
183            pointer,
184            pointer.add(1),
185            self.length - index
186        )};
187        let reference = unsafe {self.data.get_unchecked_mut(index).write(value)};
188        self.length += 1;
189        return reference;
190    }
191    pub const fn remove(&mut self, index: usize) -> Type {
192        assert!(index < self.length, "tried to remove out of bounds");
193        let value = unsafe {self.data.get_unchecked(index).assume_init_read()};
194        let pointer = unsafe {self.data.as_mut_ptr().add(index)};
195        unsafe {copy(
196            pointer.add(1),
197            pointer,
198            self.length - index - 1
199        )};
200        self.length -= 1;
201        return value;
202    }
203    pub const fn swap_remove(&mut self, index: usize) -> Type {
204        assert!(index < self.length - 1, "tried to remove out of bounds");
205        let value = unsafe {self.data[index].assume_init_read()};
206        self.data.swap(index, self.length - 1);
207        self.length -= 1;
208        return value;
209    }
210    pub const fn retain(
211        &mut self, 
212        mut closure: impl [const] FnMut(&mut Type) -> bool + [const] Destruct
213    ) -> () where Type: [const] Destruct {
214        let mut offset = 0;
215        for index in (0..self.length).const_into_iter() {
216            let mut item = unsafe {self.data[index].assume_init_read()};
217            match (closure(&mut item), offset == 0) {
218                (true, true) => forget(item),
219                (true, false) => {self.data[index - offset].write(item);},
220                (false, _) => {
221                    drop(item);
222                    offset += 1;
223                }
224            }
225        }
226        self.length -= offset;
227    }
228    pub const fn dedup(&mut self) -> () where Type: [const] PartialEq<Type> + [const] Destruct {
229        self.dedup_by(const |first, second| (first as &Type).eq(second as &Type));
230    }
231    pub const fn dedup_by(
232        &mut self, 
233        mut decider: impl [const] FnMut(&mut Type, &mut Type) -> bool + [const] Destruct
234    ) -> () where Type: [const] Destruct {
235        if self.length < 2 {return}
236        let mut offset = 0;
237        let mut first = None;
238        for index in (0..self.length).const_into_iter() {
239            let mut second = unsafe {self.data[index].assume_init_read()};
240            if first.is_none() {
241                first = Some(second);
242                continue;
243            }
244            if decider(first.as_mut().unwrap(), &mut second) {
245                drop(second);
246                offset += 1;
247            } else {
248                if offset == 0 {
249                    forget(first.replace(second).unwrap());
250                } else {
251                    let pointer = self.data[index - offset].write(second) as *mut Type;
252                    forget(first.replace(
253                        unsafe {pointer.read()}
254                    ).unwrap());
255                }
256            }
257        }
258        self.length.sub_assign(offset);
259    }
260    pub const fn dedup_by_key<Key: [const] PartialEq<Key> + [const] Destruct>(
261        &mut self,
262        mut transformation: impl [const] FnMut(&mut Type) -> Key + [const] Destruct
263    ) -> () where Type: [const] Destruct {
264        self.dedup_by(const |first, second| transformation(first) == transformation(second));
265    }
266    pub const fn drain(
267        &mut self, 
268        range: impl [const] RangeBounds<usize> + [const] Destruct
269    ) -> Self {
270        let start = match range.start_bound() {
271            Bound::Excluded(_) => unreachable!(),
272            Bound::Included(bound) => { // 2.. => 2
273                assert!(*bound < self.length);
274                *bound
275            },
276            Bound::Unbounded => 0
277        };
278        let end = match range.end_bound() {
279            Bound::Excluded(bound) => { // ..2 => 2
280                assert!(*bound <= self.length);
281                *bound
282            },
283            Bound::Included(bound) => { // ..=2 => 3
284                assert!(*bound < self.length);
285                *bound + 1
286            },
287            Bound::Unbounded => self.length
288        };
289        let mut additional = MaybeUninit::<[Type; N]>::uninit().transpose();
290        let array = match end - start {
291            0 => Array {
292                length: 0,
293                data: additional
294            },
295            1 => {
296                additional[0].write(self.remove(start));
297                Array {
298                    length: 1,
299                    data: additional
300                }
301            },
302            amount => {
303                for index in (start..end).const_into_iter() {
304                    additional[index - start].write(unsafe {
305                        self.data[index].assume_init_read()
306                    });
307                }
308                for index in (end..self.length).const_into_iter() {
309                    self.data[index - end + start].write(unsafe {
310                        self.data[index].assume_init_read()
311                    });
312                }
313                self.length -= end - start;
314                Array {
315                    length: amount,
316                    data: additional
317                }
318            }
319        };
320        return array;
321    }
322}
323
324//> ARRAY -> DROP
325const impl<Type: [const] Destruct, const N: usize> Drop for Array<Type, N> {
326    fn drop(&mut self) {self.clear()}
327}
328
329//> ARRAY -> DEBUG
330impl<Type: Debug, const N: usize> Debug for Array<Type, N> {
331    fn fmt(&self, formatter: &mut Formatter<'_>) -> Format {
332        return Debug::fmt(self.as_ref(), formatter);
333    }
334}
335
336//> ARRAY -> EXTEND
337impl<Type, const N: usize> Extend<Type> for Array<Type, N> {
338    fn extend<T: IntoIterator<Item = Type>>(&mut self, iter: T) {
339        iter.into_iter().for_each(|item| self.push(item));
340    }
341}
342
343//> ARRAY -> CLONE
344const impl<Type: [const] Clone, const N: usize> Clone for Array<Type, N> {
345    fn clone(&self) -> Self {return Array {
346        length: self.length,
347        data: arrayfn(const |index| if index >= self.length {MaybeUninit::uninit()} else {
348            MaybeUninit::new(unsafe {self.data[index].assume_init_ref().clone()})
349        })
350    }}
351}
352
353//> ARRAY -> DEFAULT
354const impl<Type, const N: usize> Default for Array<Type, N> {
355    fn default() -> Self {return Self {
356        data: MaybeUninit::uninit().transpose(),
357        length: 0
358    }}
359}
360
361pub fn test(x: u8, mut array: Array<u8, 4>) -> () {
362    array.push(x);
363}