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