Skip to main content

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