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