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_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::copy
61};
62
63//> HEAD -> CONSTRANGEITER
64use libutils_constrangeiter::ConstIntoIterator;
65
66
67//^
68//^ ARRAY
69//^
70
71//> ARRAY -> STRUCT
72pub struct Array<Type, const N: usize> {
73    length: usize,
74    data: MaybeUninit<[Type; N]>
75}
76
77//> ARRAY -> IMPLEMENTATION
78impl<Type, const N: usize> Array<Type, N> {
79    pub const fn new() -> Self {return Self::default()}
80    pub const fn as_ptr(&self) -> *const Type {return self.data.as_ptr().cast()}
81    pub const fn as_mut_ptr(&mut self) -> *mut Type {return self.data.as_mut_ptr().cast()}
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 retain(
124        &mut self, 
125        mut closure: impl [const] FnMut(&mut Type) -> bool + [const] Destruct
126    ) -> () where Type: [const] Destruct {
127        let mut offset = 0;
128        for position in (0..self.length).const_into_iter() {
129            let mut item = unsafe {self.as_mut_ptr().add(position).read()};
130            if closure(&mut item) {
131                if offset == 0 {
132                    forget(item);
133                } else {
134                    unsafe {self.as_mut_ptr().add(position).sub(offset).write(item)}
135                }
136            } else {
137                drop(item);
138                offset += 1;
139            }
140        }
141        self.length.sub_assign(offset);
142    }
143    pub const fn dedup(&mut self) -> () where Type: [const] PartialEq<Type> + [const] Destruct {
144        let mut offset = 0;
145        for position in (0..self.length - 1).const_into_iter() {
146            let first = unsafe {self.as_ptr().add(position).read()};
147            let second = unsafe {self.as_ptr().add(position).add(1).read()};
148            if first.eq(&second) {
149                if offset == 0 {
150                    forget(first)
151                } else {
152                    unsafe {self.as_mut_ptr().add(position).sub(offset).write(first)};
153                }
154                drop(second);
155                offset += 1;
156            } else {
157                if offset == 0 {
158                    forget(first);
159                    forget(second);
160                } else {
161                    unsafe {self.as_mut_ptr().add(position).sub(offset).write(first)};
162                    unsafe {self.as_mut_ptr().add(position).sub(offset).add(1).write(second)};
163                }
164            }
165        }
166        self.length.sub_assign(offset);
167    }
168}
169
170//> ARRAY -> DROP
171const impl<Type: [const] Destruct, const N: usize> Drop for Array<Type, N> {
172    fn drop(&mut self) {self.clear()}
173}
174
175//> ARRAY -> DEBUG
176impl<Type: Debug, const N: usize> Debug for Array<Type, N> {
177    fn fmt(&self, formatter: &mut Formatter<'_>) -> Format {Debug::fmt(self.as_ref(), formatter)}
178}
179
180//> ARRAY -> EXTEND
181impl<Type, const N: usize> Extend<Type> for Array<Type, N> {
182    fn extend<T: IntoIterator<Item = Type>>(&mut self, iter: T) {for item in iter {self.push(item)}}
183}
184
185//> ARRAY -> CLONE
186const impl<Type: [const] Clone, const N: usize> Clone for Array<Type, N> {
187    fn clone(&self) -> Self {
188        let mut array = Array::new();
189        for position in (0..self.length).const_into_iter() {array.push(self[position].clone())}
190        return array;
191    }
192}
193
194//> ARRAY -> DEFAULT
195const impl<Type, const N: usize> Default for Array<Type, N> {
196    fn default() -> Self {return Self {
197        data: MaybeUninit::uninit(),
198        length: 0
199    }}
200}