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(deref_pure_trait)]
15#![feature(const_array)]
16#![feature(transmute_neo)]
17#![feature(const_closures)]
18#![feature(const_trait_impl)]
19#![feature(box_vec_non_null)]
20#![feature(trusted_len)]
21#![feature(const_clone)]
22#![feature(new_range)]
23#![feature(const_slice_make_iter)]
24#![feature(test)]
25#![feature(const_ops)]
26#![feature(generic_const_exprs)]
27#![feature(const_iter)]
28#![feature(const_convert)]
29#![feature(const_default)]
30
31//> HEAD -> CRATES
32extern crate alloc;
33extern crate test;
34
35//> HEAD -> MODULES
36#[cfg(test)]
37mod benches;
38mod comparisons;
39mod conversions;
40mod iterators;
41mod references;
42#[cfg(test)]
43mod tests;
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    }, 
57    ops::{
58        Drop, 
59        SubAssign
60    }, 
61    ptr::copy
62};
63
64//> HEAD -> CONSTRANGEITER
65use constrangeiter::ConstIntoIterator;
66
67
68//^
69//^ ARRAY
70//^
71
72//> ARRAY -> STRUCT
73pub struct Array<Type, const N: usize> {
74    length: usize,
75    data: MaybeUninit<[Type; N]>
76}
77
78//> ARRAY -> IMPLEMENTATION
79impl<Type, const N: usize> Array<Type, N> {
80    pub const fn new() -> Self {return Self::default()}
81    pub const fn is_full(&self) -> bool {return self.length == N}
82    pub const fn push(&mut self, value: Type) -> () {
83        assert!(self.length != N, "array capacity exceeded");
84        unsafe {self.as_mut_ptr().add(self.length).write(value)};
85        self.length += 1;
86    }
87    pub const fn push_mut<'valid>(&'valid mut self, value: Type) -> &'valid mut Type {
88        let index = self.length;
89        self.push(value);
90        return &mut self[index];
91    }
92    pub const fn pop(&mut self) -> Option<Type> {return if self.length == 0 {None} else {
93        self.length -= 1;
94        return Some(unsafe {self.as_ptr().add(self.length).read()});
95    }}
96    pub const fn clear(&mut self) -> () where Type: [const] Destruct {self.truncate(0)}
97    pub const fn truncate(&mut self, length: usize) -> () where Type: [const] Destruct {
98        for index in (length..self.length).const_into_iter() {
99            drop(unsafe {self.as_ptr().add(index).read()})
100        }
101        self.length = length;
102    }
103    pub const fn insert(&mut self, index: usize, value: Type) -> () {
104        assert!(index <= self.length, "tried to insert out of bounds");
105        assert!(self.length != N, "array capacity exceeded");
106        let pointer = unsafe {self.as_mut_ptr().add(index)};
107        unsafe {copy(pointer, pointer.add(1), self.length - index)}
108        unsafe {pointer.write(value)}
109        self.length += 1;
110    }
111    pub const fn insert_mut<'valid>(&'valid mut self, index: usize, value: Type) -> &'valid mut Type {
112        self.insert(index, value);
113        return &mut self[index];
114    }
115    pub const fn remove(&mut self, index: usize) -> Type {
116        assert!(index < self.length, "tried to remove out of bounds");
117        let pointer = unsafe {self.as_mut_ptr().add(index)};
118        let value = unsafe {pointer.read()};
119        unsafe {copy(pointer.add(1), pointer, self.length - 1 - index)};
120        self.length -= 1;
121        return value;
122    }
123    pub const fn swap_remove(&mut self, index: usize) -> Type {
124        assert!(index < self.length, "tried to remove out of bounds");
125        let pointer = unsafe {self.as_mut_ptr().add(index)};
126        let value = unsafe {pointer.read()};
127        unsafe {copy(self.as_ptr().add(self.length).sub(1), pointer, 1)}
128        self.length -= 1;
129        return value;
130    }
131    pub const fn retain(
132        &mut self, 
133        mut closure: impl [const] FnMut(&mut Type) -> bool + [const] Destruct
134    ) -> () where Type: [const] Destruct {
135        let mut offset = 0;
136        for position in (0..self.length).const_into_iter() {
137            let mut item = unsafe {self.as_mut_ptr().add(position).read()};
138            if closure(&mut item) {
139                if offset == 0 {
140                    forget(item);
141                } else {
142                    unsafe {self.as_mut_ptr().add(position).sub(offset).write(item)}
143                }
144            } else {
145                drop(item);
146                offset += 1;
147            }
148        }
149        self.length.sub_assign(offset);
150    }
151    pub const fn dedup(&mut self) -> () where Type: [const] PartialEq<Type> + [const] Destruct {
152        self.dedup_by(const |first, second| (first as &Type).eq(second as &Type));
153    }
154    pub const fn dedup_by(
155        &mut self, 
156        mut decider: impl [const] FnMut(&mut Type, &mut Type) -> bool + [const] Destruct
157    ) -> () where Type: [const] Destruct {
158        if self.length < 2 {return}
159        let mut offset = 0;
160        let mut first = None;
161        for position in (0..=self.length - 1).const_into_iter() {
162            let mut second = unsafe {self.as_ptr().add(position).read()};
163            if first.is_none() {
164                first = Some(second);
165                continue;
166            }
167            if decider(first.as_mut().unwrap(), &mut second) {
168                drop(second);
169                offset += 1;
170            } else {
171                if offset == 0 {
172                    forget(first.replace(second).unwrap());
173                } else {
174                    unsafe {self.as_mut_ptr().add(position).sub(offset).write(second)};
175                    forget(first.replace(unsafe {self.as_mut_ptr().add(position).sub(offset).read()}).unwrap());
176                }
177            }
178        }
179        self.length.sub_assign(offset);
180    }
181}
182
183//> ARRAY -> DROP
184const impl<Type: [const] Destruct, const N: usize> Drop for Array<Type, N> {
185    fn drop(&mut self) {self.clear()}
186}
187
188//> ARRAY -> DEBUG
189impl<Type: Debug, const N: usize> Debug for Array<Type, N> {
190    fn fmt(&self, formatter: &mut Formatter<'_>) -> Format {Debug::fmt(self.as_ref(), formatter)}
191}
192
193//> ARRAY -> EXTEND
194impl<Type, const N: usize> Extend<Type> for Array<Type, N> {
195    fn extend<T: IntoIterator<Item = Type>>(&mut self, iter: T) {for item in iter {self.push(item)}}
196}
197
198//> ARRAY -> CLONE
199const impl<Type: [const] Clone, const N: usize> Clone for Array<Type, N> {
200    fn clone(&self) -> Self {
201        let mut array = Array::new();
202        for position in (0..self.length).const_into_iter() {array.push(self[position].clone())}
203        return array;
204    }
205}
206
207//> ARRAY -> DEFAULT
208const impl<Type, const N: usize> Default for Array<Type, N> {
209    fn default() -> Self {return Self {
210        data: MaybeUninit::uninit(),
211        length: 0
212    }}
213}