1use super::*;
2
3/// A WinRT array stores elements contiguously in a heap-allocated buffer.
4pub struct Array<T: Type<T>> {
5 data: *mut T::Default,
6 len: u32,
7}
8
9impl<T: Type<T>> Default for Array<T> {
10 fn default() -> Self {
11 Array { data: std::ptr::null_mut(), len: 0 }
12 }
13}
14
15impl<T: Type<T>> Array<T> {
16 /// Creates an empty array.
17 pub fn new() -> Self {
18 Self::default()
19 }
20
21 /// Creates an array of the given length with default values.
22 pub fn with_len(len: usize) -> Self {
23 assert!(len < std::u32::MAX as usize);
24 let bytes_amount = len.checked_mul(std::mem::size_of::<T>()).expect("Attempted to allocate too large an Array");
25
26 // WinRT arrays must be allocated with CoTaskMemAlloc.
27 // SAFETY: the call to CoTaskMemAlloc is safe to perform
28 // if len is zero and overflow was checked above.
29 // We ensured we alloc enough space by multiplying len * size_of::<T>
30 let data = unsafe { crate::imp::CoTaskMemAlloc(bytes_amount) as *mut T::Default };
31
32 assert!(!data.is_null(), "Could not successfully allocate for Array");
33
34 // SAFETY: It is by definition safe to zero-initialize WinRT types.
35 // `write_bytes` will write 0 to (len * size_of::<T>())
36 // bytes making the entire array zero initialized. We have assured
37 // above that the data ptr is not null.
38 unsafe {
39 std::ptr::write_bytes(data, 0, len);
40 }
41
42 let len = len as u32;
43 Self { data, len }
44 }
45
46 /// Creates an array by copying the elements from the slice.
47 pub fn from_slice(values: &[T::Default]) -> Self
48 where
49 T::Default: Clone,
50 {
51 let mut array = Self::with_len(values.len());
52 array.clone_from_slice(values);
53 array
54 }
55
56 /// Creates an array from a pointer and length. The `len` argument is the number of elements, not the number of bytes.
57 /// # Safety
58 /// The `data` argument must have been allocated with `CoTaskMemAlloc`.
59 pub unsafe fn from_raw_parts(data: *mut T::Default, len: u32) -> Self {
60 Self { data, len }
61 }
62
63 /// Returns a slice containing the entire array.
64 pub fn as_slice(&self) -> &[T::Default] {
65 self
66 }
67
68 /// Returns `true` if the array is empty.
69 pub fn is_empty(&self) -> bool {
70 self.len == 0
71 }
72
73 /// Returns the length of the array.
74 pub fn len(&self) -> usize {
75 self.len as usize
76 }
77
78 /// Clears the contents of the array.
79 pub fn clear(&mut self) {
80 if self.is_empty() {
81 return;
82 }
83
84 let mut data = std::ptr::null_mut();
85 let mut len = 0;
86
87 std::mem::swap(&mut data, &mut self.data);
88 std::mem::swap(&mut len, &mut self.len);
89
90 // SAFETY: At this point, self has been reset to zero so any panics in T's destructor would
91 // only leak data not leave the array in bad state.
92 unsafe {
93 // Call the destructors of all the elements of the old array
94 // SAFETY: the slice cannot be used after the call to `drop_in_place`
95 std::ptr::drop_in_place(std::slice::from_raw_parts_mut(data, len as usize));
96 // Free the data memory where the elements were
97 // SAFETY: we have unique access to the data pointer at this point
98 // so freeing it is the right thing to do
99 crate::imp::CoTaskMemFree(data as _);
100 }
101 }
102
103 #[doc(hidden)]
104 /// Get a mutable pointer to the array's length
105 ///
106 /// # Safety
107 ///
108 /// This function is safe but writing to the pointer is not. Calling this without
109 /// a subsequent call to `set_abi` is likely to either leak memory or cause UB
110 pub unsafe fn set_abi_len(&mut self) -> *mut u32 {
111 &mut self.len
112 }
113
114 #[doc(hidden)]
115 /// Turn the array into a pointer to its data and its length
116 pub fn into_abi(self) -> (*mut T::Abi, u32) {
117 let abi = (self.data as *mut _, self.len);
118 std::mem::forget(self);
119 abi
120 }
121}
122
123impl<T: Type<T>> std::ops::Deref for Array<T> {
124 type Target = [T::Default];
125
126 fn deref(&self) -> &[T::Default] {
127 if self.is_empty() {
128 return &[];
129 }
130
131 // SAFETY: data must not be null if the array is not empty
132 unsafe { std::slice::from_raw_parts(self.data, self.len as usize) }
133 }
134}
135
136impl<T: Type<T>> std::ops::DerefMut for Array<T> {
137 fn deref_mut(&mut self) -> &mut [T::Default] {
138 if self.is_empty() {
139 return &mut [];
140 }
141
142 // SAFETY: data must not be null if the array is not empty
143 unsafe { std::slice::from_raw_parts_mut(self.data, self.len as usize) }
144 }
145}
146
147impl<T: Type<T>> Drop for Array<T> {
148 fn drop(&mut self) {
149 self.clear();
150 }
151}
152
153#[doc(hidden)]
154pub struct ArrayProxy<T: Type<T>> {
155 data: *mut *mut T::Default,
156 len: *mut u32,
157 temp: std::mem::ManuallyDrop<Array<T>>,
158}
159
160impl<T: Type<T>> ArrayProxy<T> {
161 pub fn from_raw_parts(data: *mut *mut T::Default, len: *mut u32) -> Self {
162 Self { data, len, temp: std::mem::ManuallyDrop::new(Array::new()) }
163 }
164
165 pub fn as_array(&mut self) -> &mut Array<T> {
166 &mut self.temp
167 }
168}
169
170impl<T: Type<T>> Drop for ArrayProxy<T> {
171 fn drop(&mut self) {
172 unsafe {
173 *self.data = self.temp.data;
174 *self.len = self.temp.len;
175 }
176 }
177}
178