use alloc::vec::Vec;
use core::ffi::c_void;
use core::ptr::NonNull;
use crate::capi_state::CApiState;
use crate::ctypes::*;
#[derive(Debug)]
pub(super) struct OpenFile {
handle: NonNull<COpenFile>,
closed: bool,
}
impl OpenFile {
pub(super) fn new(handle: NonNull<COpenFile>) -> Self {
OpenFile {
handle,
closed: false,
}
}
pub fn read_file(&mut self) -> Option<Vec<u8>> {
let mut out = Vec::new();
const BUF_SIZE: u32 = 256;
let mut buf = [0; BUF_SIZE as usize];
loop {
let result = unsafe {
Self::fns().read.unwrap()(self.cptr_mut(), buf.as_mut_ptr() as *mut c_void, BUF_SIZE)
};
let bytes = match result {
0 => break,
-1 => None?,
read_bytes_count => read_bytes_count as usize,
};
out.extend(buf[0..bytes].into_iter());
}
Some(out)
}
pub fn write_file(&mut self, contents: &[u8]) -> bool {
const BUF_SIZE: usize = 256;
for buf in contents.chunks(BUF_SIZE) {
let mut written_from_buffer = 0;
loop {
let result = unsafe {
Self::fns().write.unwrap()(
self.cptr_mut().add(written_from_buffer),
buf.as_ptr() as *const c_void,
(buf.len() - written_from_buffer) as u32,
)
};
written_from_buffer += match result {
-1 => return false,
written_bytes_count => written_bytes_count as usize,
};
if written_from_buffer == buf.len() {
break;
}
}
}
true
}
#[must_use]
pub fn close(mut self) -> bool {
self.closed = true;
let result = unsafe { Self::fns().close.unwrap()(self.cptr_mut()) };
result == 0
}
pub(crate) fn cptr_mut(&mut self) -> *mut COpenFile {
self.handle.as_ptr()
}
pub(crate) fn fns() -> &'static craydate_sys::playdate_file {
CApiState::get().cfile
}
}
impl Drop for OpenFile {
fn drop(&mut self) {
if !self.closed {
crate::log::log("ERROR: OpenFile dropped without calling close()");
assert!(self.closed);
}
}
}