Skip to main content

libutils_array/
mod.rs

1//^
2//^ HEAD
3//^
4
5//> HEAD -> NO_STD
6#![no_std]
7
8//> HEAD -> LINTS
9#![allow(incomplete_features)]
10
11//> HEAD -> FEATURES
12#![feature(const_cmp)]
13#![feature(const_destruct)]
14#![feature(const_array)]
15#![feature(transmute_neo)]
16#![feature(const_closures)]
17#![feature(const_trait_impl)]
18#![feature(box_vec_non_null)]
19#![feature(trusted_len)]
20#![feature(const_clone)]
21#![feature(new_range)]
22#![feature(const_slice_make_iter)]
23#![feature(test)]
24#![feature(const_ops)]
25#![feature(generic_const_exprs)]
26#![feature(const_iter)]
27#![feature(const_convert)]
28#![feature(const_default)]
29
30//> HEAD -> CRATES
31extern crate alloc;
32extern crate test;
33
34//> HEAD -> MODULES
35#[cfg(test)]
36mod benches;
37mod comparisons;
38mod conversions;
39mod iterators;
40mod references;
41#[cfg(test)]
42mod tests;
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    }, 
56    ops::{
57        Drop, 
58        SubAssign
59    }, 
60    ptr::{
61        copy,
62        copy_nonoverlapping
63    }
64};
65
66//> HEAD -> CONSTRANGEITER
67use constrangeiter::ConstIntoIterator;
68
69
70//^
71//^ ARRAY
72//^
73
74//> ARRAY -> STRUCT
75pub struct Array<Type, const N: usize> {
76    length: usize,
77    data: MaybeUninit<[Type; N]>
78}
79
80//> ARRAY -> IMPLEMENTATION
81impl<Type, const N: usize> Array<Type, N> {
82    pub const fn new() -> Self {return Self::default()}
83    pub const fn is_full(&self) -> bool {return self.length == N}
84    pub const fn repeat<
85        const TIMES: usize
86    >(self) -> Array<Type, {TIMES * N}> where Type: [const] Clone + [const] Destruct, [(); TIMES * N]: {
87        let (length, data) = self.into();
88        let mut additional = MaybeUninit::<[Type; TIMES * N]>::uninit();
89        if N == 0 {for index in (0..length).const_into_iter() {
90            drop(unsafe {data.as_ptr().cast::<Type>().add(index).read()});
91        }} else {
92            unsafe {copy_nonoverlapping(
93                data.as_ptr().cast::<Type>(),
94                additional.as_mut_ptr().cast::<Type>(), 
95                length
96            )};
97            for iteration in (1..TIMES).const_into_iter() {
98                for index in (0..length).const_into_iter() {
99                    unsafe {additional.as_mut_ptr().cast::<Type>().add(length * iteration).add(index).write(
100                        data.as_ptr().cast::<Type>().add(index).as_ref().unwrap().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, data) = self.into();
109        let mut additional = MaybeUninit::<[Type; M]>::uninit();
110        return if M >= length {
111            unsafe {copy_nonoverlapping(
112                data.as_ptr().cast::<Type>(), 
113                additional.as_mut_ptr().cast::<Type>(), 
114                length
115            )};
116            Array::from((length, additional))
117        } else {
118            unsafe {copy_nonoverlapping(
119                data.as_ptr().cast::<Type>(), 
120                additional.as_mut_ptr().cast::<Type>(), 
121                M
122            )};
123            for index in (M..length).const_into_iter() {
124                drop(unsafe {data.as_ptr().cast::<Type>().add(index).read()});
125            };
126            Array::from((M, additional))
127        }
128    }
129    pub const fn push(&mut self, value: Type) -> () {
130        assert!(self.length != N, "array capacity exceeded");
131        unsafe {self.as_mut_ptr().add(self.length).write(value)};
132        self.length += 1;
133    }
134    pub const fn push_mut<'valid>(&'valid mut self, value: Type) -> &'valid mut Type {
135        let index = self.length;
136        self.push(value);
137        return &mut self[index];
138    }
139    pub const fn pop(&mut self) -> Option<Type> {return if self.length == 0 {None} else {
140        self.length -= 1;
141        return Some(unsafe {self.as_ptr().add(self.length).read()});
142    }}
143    pub const fn clear(&mut self) -> () where Type: [const] Destruct {self.truncate(0)}
144    pub const fn truncate(&mut self, length: usize) -> () where Type: [const] Destruct {
145        for index in (length..self.length).const_into_iter() {
146            drop(unsafe {self.as_ptr().add(index).read()})
147        }
148        self.length = length;
149    }
150    pub const fn insert(&mut self, index: usize, value: Type) -> () {
151        assert!(index <= self.length, "tried to insert out of bounds");
152        assert!(self.length != N, "array capacity exceeded");
153        let pointer = unsafe {self.as_mut_ptr().add(index)};
154        unsafe {copy(pointer, pointer.add(1), self.length - index)}
155        unsafe {pointer.write(value)}
156        self.length += 1;
157    }
158    pub const fn insert_mut<'valid>(&'valid mut self, index: usize, value: Type) -> &'valid mut Type {
159        self.insert(index, value);
160        return &mut self[index];
161    }
162    pub const fn remove(&mut self, index: usize) -> Type {
163        assert!(index < self.length, "tried to remove out of bounds");
164        let pointer = unsafe {self.as_mut_ptr().add(index)};
165        let value = unsafe {pointer.read()};
166        unsafe {copy(pointer.add(1), pointer, self.length - 1 - index)};
167        self.length -= 1;
168        return value;
169    }
170    pub const fn swap_remove(&mut self, index: usize) -> Type {
171        assert!(index < self.length, "tried to remove out of bounds");
172        let pointer = unsafe {self.as_mut_ptr().add(index)};
173        let value = unsafe {pointer.read()};
174        unsafe {copy(self.as_ptr().add(self.length).sub(1), pointer, 1)}
175        self.length -= 1;
176        return value;
177    }
178    pub const fn retain(
179        &mut self, 
180        mut closure: impl [const] FnMut(&mut Type) -> bool + [const] Destruct
181    ) -> () where Type: [const] Destruct {
182        let mut offset = 0;
183        for position in (0..self.length).const_into_iter() {
184            let mut item = unsafe {self.as_mut_ptr().add(position).read()};
185            if closure(&mut item) {
186                if offset == 0 {
187                    forget(item);
188                } else {
189                    unsafe {self.as_mut_ptr().add(position).sub(offset).write(item)}
190                }
191            } else {
192                drop(item);
193                offset += 1;
194            }
195        }
196        self.length.sub_assign(offset);
197    }
198    pub const fn dedup(&mut self) -> () where Type: [const] PartialEq<Type> + [const] Destruct {
199        self.dedup_by(const |first, second| (first as &Type).eq(second as &Type));
200    }
201    pub const fn dedup_by(
202        &mut self, 
203        mut decider: impl [const] FnMut(&mut Type, &mut Type) -> bool + [const] Destruct
204    ) -> () where Type: [const] Destruct {
205        if self.length < 2 {return}
206        let mut offset = 0;
207        let mut first = None;
208        for position in (0..=self.length - 1).const_into_iter() {
209            let mut second = unsafe {self.as_ptr().add(position).read()};
210            if first.is_none() {
211                first = Some(second);
212                continue;
213            }
214            if decider(first.as_mut().unwrap(), &mut second) {
215                drop(second);
216                offset += 1;
217            } else {
218                if offset == 0 {
219                    forget(first.replace(second).unwrap());
220                } else {
221                    unsafe {self.as_mut_ptr().add(position).sub(offset).write(second)};
222                    forget(first.replace(unsafe {self.as_mut_ptr().add(position).sub(offset).read()}).unwrap());
223                }
224            }
225        }
226        self.length.sub_assign(offset);
227    }
228    pub const fn dedup_by_key<Key: [const] PartialEq<Key> + [const] Destruct>(
229        &mut self,
230        mut transformation: impl [const] FnMut(&mut Type) -> Key + [const] Destruct
231    ) -> () where Type: [const] Destruct {
232        self.dedup_by(const |first, second| transformation(first) == transformation(second));
233    }
234}
235
236//> ARRAY -> DROP
237const impl<Type: [const] Destruct, const N: usize> Drop for Array<Type, N> {
238    fn drop(&mut self) {self.clear()}
239}
240
241//> ARRAY -> DEBUG
242impl<Type: Debug, const N: usize> Debug for Array<Type, N> {
243    fn fmt(&self, formatter: &mut Formatter<'_>) -> Format {Debug::fmt(self.as_ref(), formatter)}
244}
245
246//> ARRAY -> EXTEND
247impl<Type, const N: usize> Extend<Type> for Array<Type, N> {
248    fn extend<T: IntoIterator<Item = Type>>(&mut self, iter: T) {for item in iter {self.push(item)}}
249}
250
251//> ARRAY -> CLONE
252const impl<Type: [const] Clone, const N: usize> Clone for Array<Type, N> {
253    fn clone(&self) -> Self {
254        let mut array = Array::new();
255        for position in (0..self.length).const_into_iter() {array.push(self[position].clone())}
256        return array;
257    }
258}
259
260//> ARRAY -> DEFAULT
261const impl<Type, const N: usize> Default for Array<Type, N> {
262    fn default() -> Self {return Self {
263        data: MaybeUninit::uninit(),
264        length: 0
265    }}
266}