1use core::{
2 ops::{Deref, DerefMut},
3 ptr::{NonNull, slice_from_raw_parts, slice_from_raw_parts_mut},
4};
5
6use alloc::{boxed::Box, vec::Vec};
7
8use super::{IntoFFI, IntoRust};
9
10pub type WuiData = WuiArray<u8>;
12
13#[repr(C)]
19pub struct WuiArray<T: 'static> {
20 data: NonNull<()>,
22 vtable: WuiArrayVTable<T>,
23}
24
25#[repr(C)]
26pub struct WuiArrayVTable<T> {
27 drop: unsafe extern "C" fn(*mut ()),
28 slice: unsafe extern "C" fn(*const ()) -> WuiArraySlice<T>,
29}
30
31#[repr(C)]
32pub struct WuiArraySlice<T> {
33 head: *mut T,
34 len: usize,
35}
36
37impl<T> WuiArrayVTable<T> {
38 pub const fn from_raw(
39 drop: unsafe extern "C" fn(*mut ()),
40 slice: unsafe extern "C" fn(*const ()) -> WuiArraySlice<T>,
41 ) -> Self {
42 Self { drop, slice }
43 }
44
45 pub const fn new<U>() -> Self
46 where
47 U: AsRef<[T]> + 'static,
48 {
49 unsafe extern "C" fn drop<U2>(data: *mut ()) {
50 unsafe {
51 let _: Box<U2> = Box::from_raw(data as *mut U2);
52 }
53 }
54
55 unsafe extern "C" fn slice<U2, T2>(data: *const ()) -> WuiArraySlice<T2>
56 where
57 U2: AsRef<[T2]>,
58 {
59 unsafe {
60 let slice = &*data.cast::<U2>();
61 let s = slice.as_ref();
62 let len = s.len();
63 let head = s.as_ptr() as *mut T2;
64 WuiArraySlice { head, len }
65 }
66 }
67
68 Self {
69 drop: drop::<U>,
70 slice: slice::<U, T>,
71 }
72 }
73}
74
75impl<T> WuiArray<T> {
76 pub const unsafe fn from_raw(data: *mut (), vtable: WuiArrayVTable<T>) -> Self {
83 Self {
84 data: unsafe { NonNull::new_unchecked(data) },
85 vtable,
86 }
87 }
88
89 pub fn new<U>(array: U) -> Self
90 where
91 U: AsRef<[T]> + 'static,
92 {
93 let boxed = Box::new(array);
94 let data = Box::into_raw(boxed) as *mut ();
95 let vtable = WuiArrayVTable::new::<U>();
96 unsafe { Self::from_raw(data, vtable) }
97 }
98
99 pub fn len(&self) -> usize {
100 self.as_slice().len()
101 }
102
103 pub fn is_empty(&self) -> bool {
104 self.len() == 0
105 }
106
107 pub fn as_slice(&self) -> &[T] {
108 unsafe {
109 let slice = (self.vtable.slice)(self.data.as_ptr());
110 &*slice_from_raw_parts(slice.head, slice.len)
111 }
112 }
113
114 pub fn as_mut_slice(&mut self) -> &mut [T] {
115 unsafe {
116 let slice = (self.vtable.slice)(self.data.as_ptr());
117 &mut *slice_from_raw_parts_mut(slice.head, slice.len)
118 }
119 }
120}
121
122impl<T: IntoRust + Default> IntoIterator for WuiArray<T> {
123 type Item = T::Rust;
124 type IntoIter = alloc::vec::IntoIter<T::Rust>;
125 fn into_iter(self) -> Self::IntoIter {
126 unsafe { self.into_rust().into_iter() }
127 }
128}
129
130impl<T> Deref for WuiArray<T> {
131 type Target = [T];
132 fn deref(&self) -> &Self::Target {
133 self.as_slice()
134 }
135}
136
137impl<T> DerefMut for WuiArray<T> {
138 fn deref_mut(&mut self) -> &mut Self::Target {
139 self.as_mut_slice()
140 }
141}
142
143impl<T> AsRef<[T]> for WuiArray<T> {
144 fn as_ref(&self) -> &[T] {
145 self
146 }
147}
148
149impl<T: IntoFFI> IntoFFI for Vec<T>
150where
151 <T as IntoFFI>::FFI: 'static,
152{
153 type FFI = WuiArray<T::FFI>;
154
155 fn into_ffi(self) -> Self::FFI {
156 WuiArray::new(
157 self.into_iter()
158 .map(|item| item.into_ffi())
159 .collect::<Vec<_>>(),
160 )
161 }
162}
163
164impl<T: Default + IntoRust> IntoRust for WuiArray<T> {
165 type Rust = Vec<T::Rust>;
166 unsafe fn into_rust(mut self) -> Self::Rust {
167 self.deref_mut()
168 .iter_mut()
169 .map(|item| unsafe { core::mem::take(item).into_rust() })
170 .collect::<Vec<_>>()
171 }
172}