1use crate::sys::*;
7use log;
8use std::{
9 ffi::c_void,
10 fmt::Debug,
11 io::{Read, Seek, SeekFrom, Write},
12 marker::PhantomData,
13};
14
15pub trait RWSeekable: Read + Write + Seek {
17 fn as_mut_dyn(&mut self) -> &mut dyn RWSeekable;
22}
23
24impl<T: Read + Write + Seek> RWSeekable for T {
25 fn as_mut_dyn(&mut self) -> &mut dyn RWSeekable {
26 self
27 }
28}
29
30impl<'a> Debug for dyn RWSeekable + 'a {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 write!(f, "RWSeekable({:p})", self)
33 }
34}
35
36#[allow(unused)]
38pub struct RustKtxStream<'a, T: RWSeekable + ?Sized + 'a> {
39 inner_ptr: Option<*mut T>,
40 ktx_stream: Option<Box<ktxStream>>,
41 ktx_phantom: PhantomData<&'a ktxStream>,
42}
43
44impl<'a, T: RWSeekable + ?Sized + 'a> RustKtxStream<'a, T> {
45 pub fn new(inner: Box<T>) -> Result<Self, ktx_error_code_e> {
47 let inner_ptr = Box::into_raw(inner);
48 let inner_rwseekable_ptr = unsafe { (*inner_ptr).as_mut_dyn() } as *mut dyn RWSeekable;
50 let (t_addr, vtable_addr): (*mut c_void, *mut c_void) =
52 unsafe { std::mem::transmute(inner_rwseekable_ptr) };
53
54 let mut ktx_stream = Box::new(ktxStream {
55 read: Some(ktxRustStream_read),
56 skip: Some(ktxRustStream_skip),
57 write: Some(ktxRustStream_write),
58 getpos: Some(ktxRustStream_getpos),
59 setpos: Some(ktxRustStream_setpos),
60 getsize: Some(ktxRustStream_getsize),
61 destruct: Some(ktxRustStream_destruct),
62 closeOnDestruct: false,
64 type_: streamType_eStreamTypeCustom,
66 data: unsafe { std::mem::zeroed() },
67 readpos: 0,
68 });
69 let custom_ptr = unsafe { ktx_stream.data.custom_ptr.as_mut() };
70 custom_ptr.address = t_addr;
71 custom_ptr.allocatorAddress = vtable_addr;
72 custom_ptr.size = 0;
73
74 Ok(Self {
75 inner_ptr: Some(inner_ptr),
76 ktx_stream: Some(ktx_stream),
77 ktx_phantom: PhantomData,
78 })
79 }
80
81 pub fn ktx_stream(&self) -> *mut ktxStream {
87 match &self.ktx_stream {
88 Some(boxed) => unsafe { std::mem::transmute(boxed.as_ref()) },
91 None => std::ptr::null_mut(),
92 }
93 }
94
95 pub fn inner(&self) -> &T {
97 unsafe { &*self.inner_ptr.expect("Self was destroyed") as &T }
99 }
100
101 pub fn inner_mut(&mut self) -> &mut T {
103 unsafe { &mut *self.inner_ptr.expect("Self was destroyed") as &mut T }
105 }
106
107 fn rebox_inner_ptr(&mut self) -> Box<T> {
109 let moved_t = std::mem::replace(&mut self.inner_ptr, unsafe { std::mem::zeroed() });
111 unsafe {
112 Box::from_raw(moved_t.expect("Self was already destroyed"))
114 }
115 }
116
117 pub fn into_inner(mut self) -> Box<T> {
119 self.rebox_inner_ptr()
120 }
121}
122
123impl<'a, T: RWSeekable + ?Sized + 'a> Drop for RustKtxStream<'a, T> {
124 fn drop(&mut self) {
125 let mut moved_self = std::mem::replace(
127 self,
128 RustKtxStream {
129 inner_ptr: None,
130 ktx_stream: None,
131 ktx_phantom: PhantomData,
132 },
133 );
134
135 if let Some(mut ktx_stream) = std::mem::replace(&mut moved_self.ktx_stream, None) {
137 let mut custom_ptr = unsafe { ktx_stream.data.custom_ptr.as_mut() };
138 custom_ptr.address = std::ptr::null_mut();
139 custom_ptr.allocatorAddress = std::ptr::null_mut();
140 custom_ptr.size = 0xBADDA7A;
141 std::mem::drop(ktx_stream);
142 }
143 if let Some(_) = moved_self.inner_ptr {
147 std::mem::drop(moved_self.rebox_inner_ptr())
148 }
149
150 std::mem::forget(moved_self);
153 }
154}
155
156fn format_option_ptr<T>(f: &mut std::fmt::Formatter<'_>, option: &Option<T>) -> std::fmt::Result {
157 match option {
158 Some(t) => write!(f, "{:p}", t),
159 None => write!(f, "<none>"),
160 }
161}
162
163impl<'a, T: RWSeekable + ?Sized + 'a> Debug for RustKtxStream<'a, T> {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 write!(f, "RustKtxStream(inner=")?;
166 format_option_ptr(f, &self.inner_ptr)?;
167 write!(f, ", ktxStream=")?;
168 format_option_ptr(f, &self.ktx_stream)?;
169 write!(f, ")")
170 }
171}
172
173unsafe fn inner_rwseekable<'a>(str: *mut ktxStream) -> &'a mut dyn RWSeekable {
176 let fat_t_ptr = {
177 let custom_ptr = (*str).data.custom_ptr.as_ref();
178 (custom_ptr.address, custom_ptr.allocatorAddress)
179 };
180 let inner_ref: *mut dyn RWSeekable = std::mem::transmute(fat_t_ptr);
181 &mut *inner_ref
182}
183
184fn stream_len(seek: &mut dyn RWSeekable) -> std::io::Result<u64> {
186 let old_pos = seek.stream_position()?;
187 let size = seek.seek(SeekFrom::End(0))?;
188 seek.seek(SeekFrom::Start(old_pos))?;
189 Ok(size)
190}
191
192#[no_mangle]
193unsafe extern "C" fn ktxRustStream_read(
194 str: *mut ktxStream,
195 dst: *mut c_void,
196 count: ktx_size_t,
197) -> ktx_error_code_e {
198 let inner = inner_rwseekable(str);
199 let buf = std::slice::from_raw_parts_mut(dst as *mut u8, count as usize);
200 match inner.read_exact(buf) {
201 Ok(_) => ktx_error_code_e_KTX_SUCCESS,
202 Err(err) => {
203 log::error!("ktxRustStream_read: {}", err);
204 ktx_error_code_e_KTX_FILE_READ_ERROR
205 }
206 }
207}
208
209#[no_mangle]
210unsafe extern "C" fn ktxRustStream_skip(
211 str: *mut ktxStream,
212 count: ktx_size_t,
213) -> ktx_error_code_e {
214 let inner = inner_rwseekable(str);
215 match inner.seek(SeekFrom::Current(count as i64)) {
216 Ok(_) => ktx_error_code_e_KTX_SUCCESS,
217 Err(err) => {
218 log::error!("ktxRustStream_skip: {}", err);
219 ktx_error_code_e_KTX_FILE_SEEK_ERROR
220 }
221 }
222}
223
224#[no_mangle]
225unsafe extern "C" fn ktxRustStream_write(
226 str: *mut ktxStream,
227 src: *const c_void,
228 size: ktx_size_t,
229 count: ktx_size_t,
230) -> ktx_error_code_e {
231 let inner = inner_rwseekable(str);
232 let len = (size * count) as usize;
233 let buf = std::slice::from_raw_parts(src as *const u8, len);
234 match inner.write_all(buf) {
235 Ok(_) => ktx_error_code_e_KTX_SUCCESS,
236 Err(err) => {
237 log::error!("ktxRustStream_write: {}", err);
238 ktx_error_code_e_KTX_FILE_WRITE_ERROR
239 }
240 }
241}
242
243#[no_mangle]
244unsafe extern "C" fn ktxRustStream_getpos(
245 str: *mut ktxStream,
246 pos: *mut ktx_off_t,
247) -> ktx_error_code_e {
248 let inner = inner_rwseekable(str);
249 match inner.stream_position() {
250 Ok(cur) => {
251 *pos = cur as ktx_off_t;
252 ktx_error_code_e_KTX_SUCCESS
253 }
254 Err(err) => {
255 log::error!("ktxRustStream_getpos: {}", err);
256 ktx_error_code_e_KTX_FILE_SEEK_ERROR
257 }
258 }
259}
260
261#[no_mangle]
262unsafe extern "C" fn ktxRustStream_setpos(str: *mut ktxStream, off: ktx_off_t) -> ktx_error_code_e {
263 let inner = inner_rwseekable(str);
264 match inner.seek(SeekFrom::Start(off as u64)) {
265 Ok(_) => ktx_error_code_e_KTX_SUCCESS,
266 Err(err) => {
267 log::error!("ktxRustStream_setpos: {}", err);
268 ktx_error_code_e_KTX_FILE_SEEK_ERROR
269 }
270 }
271}
272
273#[no_mangle]
274unsafe extern "C" fn ktxRustStream_getsize(
275 str: *mut ktxStream,
276 size: *mut ktx_size_t,
277) -> ktx_error_code_e {
278 let inner = inner_rwseekable(str);
279 match stream_len(inner) {
280 Ok(len) => {
281 *size = len as ktx_size_t;
282 ktx_error_code_e_KTX_SUCCESS
283 }
284 Err(err) => {
285 log::error!("ktxRustStream_getsize: {}", err);
286 ktx_error_code_e_KTX_FILE_SEEK_ERROR
287 }
288 }
289}
290
291#[no_mangle]
292unsafe extern "C" fn ktxRustStream_destruct(_str: *mut ktxStream) {
293 }