1#[derive(Debug)]
2#[repr(C)]
3pub struct ArrayBox<T> {
4 pub data: *mut T,
5 pub length: usize,
6 pub capacity: usize,
7 pub owned: bool,
8}
9
10impl<T> ArrayBox<T> {
11 pub fn new() -> Self {
12 ArrayBox {
13 length: 0,
14 capacity: 0,
15 data: std::ptr::null_mut(),
16 owned: true,
17 }
18 }
19
20 pub fn from_vector(vector: Vec<T>) -> Self {
21 let mut array = Self::new();
22 array.set_vector(vector);
23 array
24 }
25
26 pub fn from_array(array_buffer: &[T]) -> Self
28 where
29 T: Clone,
30 {
31 Self::from_vector(Vec::<T>::from(array_buffer))
32 }
33
34 pub fn from_data(data: *mut T, length: usize) -> Self {
36 ArrayBox {
37 length,
38 capacity: length,
39 data,
40 owned: false,
41 }
42 }
43
44 pub fn set_vector(&mut self, vector: Vec<T>) {
46 Self::free_buffer(self.data, self.length, self.capacity, self.owned);
48 let mut data = vector;
49 data.shrink_to_fit();
50
51 self.length = data.len();
52 self.capacity = data.capacity();
53 self.data = Self::vec_to_buffer(data)
54 }
55
56 pub fn set_array(&mut self, array_buffer: &[T])
58 where
59 T: Clone,
60 {
61 let vector = Vec::<T>::from(array_buffer);
62 self.set_vector(vector);
63 }
64
65 pub fn to_slice(&self) -> &[T] {
66 unsafe { std::slice::from_raw_parts(self.data, self.length) }
67 }
68
69 pub fn to_slice_mut(&mut self) -> &mut [T] {
70 unsafe { std::slice::from_raw_parts_mut(self.data, self.length) }
71 }
72
73 pub fn copy_into(&self, another_array: &mut ArrayBox<T>)
74 where
75 T: Copy,
76 {
77 assert!(
78 self.length <= another_array.length,
79 "The source does not fit into destination"
80 );
81 assert!(!self.data.is_null(), "The source data must not be nil");
82 assert!(
83 !another_array.data.is_null(),
84 "The destination data must not be nil"
85 );
86 unsafe { std::ptr::copy_nonoverlapping::<T>(self.data, another_array.data, self.length) }
87 }
88
89 pub fn to_vector(mut self) -> Vec<T>
90 where
91 T: Clone,
92 {
93 let vector = unsafe { Vec::from_raw_parts(self.data, self.length, self.capacity) };
94 if self.owned {
95 self.owned = false;
97 self.data = std::ptr::null_mut();
98 vector
99 } else {
100 let clone = vector.clone();
101 std::mem::forget(vector);
103 clone
104 }
105 }
106
107 pub fn at_put(&mut self, index: usize, object: T) {
108 assert!(index < self.length, "Index must be less than array length");
109
110 let slice = self.to_slice_mut();
111 slice[index] = object;
112 }
113
114 pub fn at(&self, index: usize) -> T
115 where
116 T: Clone,
117 {
118 assert!(index < self.length, "Index must be less than array length");
119
120 let slice = self.to_slice();
121 slice[index].clone()
122 }
123}
124
125impl<T> ArrayBox<T> {
126 fn vec_to_buffer(mut _data: Vec<T>) -> *mut T {
127 let _ptr = _data.as_mut_ptr();
128 std::mem::forget(_data);
129 _ptr
130 }
131
132 fn free_buffer(_ptr_data: *mut T, _length: usize, _capacity: usize, _owned: bool) {
133 if _ptr_data.is_null() {
134 return;
135 }
136 if !_owned {
137 return;
138 }
139 drop(unsafe { Vec::from_raw_parts(_ptr_data, _length, _capacity) });
140 }
141}
142
143impl<T> Default for ArrayBox<T> {
144 fn default() -> Self {
145 ArrayBox::from_vector(vec![])
146 }
147}
148
149impl<T> Drop for ArrayBox<T> {
150 fn drop(&mut self) {
151 Self::free_buffer(self.data, self.length, self.capacity, self.owned);
152 self.data = std::ptr::null_mut();
153 self.length = 0;
154 self.capacity = 0;
155 }
156}
157
158impl<T> ArrayBox<T>
159where
160 T: Default + Copy,
161{
162 pub fn byte_size(count: usize) -> usize {
163 std::mem::size_of::<T>() * count
164 }
165
166 pub fn new_with(element: T, amount: usize) -> ArrayBox<T> {
167 ArrayBox::<T>::from_vector(vec![element; amount])
168 }
169}
170
171#[cfg(test)]
172mod test {
173 use super::*;
174
175 #[test]
176 fn default_array_u8() {
177 let array = ArrayBox::<u8>::default();
178 assert_eq!(array.capacity, 0);
179 assert_eq!(array.length, 0);
180 assert!(!array.data.is_null());
181 }
182
183 #[test]
184 fn new_array_u8() {
185 let array = ArrayBox::<u8>::from_vector(vec![0, 1, 2, 3, 4]);
186 assert_eq!(array.capacity, 5);
187 assert_eq!(array.length, 5);
188 assert!(!array.data.is_null());
189 }
190}