Skip to main content

array_box/
array_box.rs

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    /// I create a copy of a given array
27    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    /// Create an array assuming that I don't own the data
35    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    /// Mutate me to hold a given vector
45    pub fn set_vector(&mut self, vector: Vec<T>) {
46        // first free existing char buffer
47        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    /// Mutate me to hold a given vector
57    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            // I do not own data anymore
96            self.owned = false;
97            self.data = std::ptr::null_mut();
98            vector
99        } else {
100            let clone = vector.clone();
101            // do not de-allocate
102            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}