1use core::ffi::c_uint;
2use alloc::vec::Vec;
3
4use sys::ffi::FileOptions;
5use sys::ffi::SDFile;
6use sys::traits::AsRaw;
7
8use crate::api;
9use crate::Path;
10use crate::ApiError;
11use crate::error::Error;
12use crate::options::FileOptionsExt;
13use crate::options::OpenOptions;
14use crate::seek::SeekFrom;
15
16
17pub trait AnyFile: AsRaw<Type = SDFile> {}
18impl<T: AsRaw<Type = SDFile>> AnyFile for T {}
19
20
21#[must_use = "File will be closed on drop"]
22#[cfg_attr(feature = "bindings-derive-debug", derive(Debug))]
23pub struct File<Api: api::Api = api::Default>(pub(crate) *mut SDFile, pub(crate) Api);
24
25impl<Api: api::Api> AsRaw for File<Api> {
31 type Type = SDFile;
32 unsafe fn as_raw(&self) -> *mut Self::Type { self.0 }
33}
34
35
36impl File<api::Default> {
37 #[must_use]
42 pub fn options() -> impl OpenOptions + FileOptionsExt { FileOptions::new() }
43}
44
45
46impl<Api: api::Api> File<Api> {
47 #[doc(alias = "sys::ffi::playdate_file::open")]
55 #[must_use]
56 pub fn open<P: AsRef<Path>>(path: P, data_dir: bool) -> Result<File<Api>, ApiError>
57 where Api: Default {
58 let api = Default::default();
59 crate::ops::open(api, path, FileOptions::new().read(true).read_data(data_dir))
60 }
61
62 #[doc(alias = "sys::ffi::playdate_file::open")]
70 #[must_use]
71 pub fn open_with<P: AsRef<Path>>(api: Api, path: P, data_dir: bool) -> Result<File<Api>, ApiError> {
72 crate::ops::open(api, path, FileOptions::new().read(true).read_data(data_dir))
73 }
74
75 #[doc(alias = "sys::ffi::playdate_file::read")]
81 #[must_use]
82 #[inline(always)]
83 pub fn read(&mut self, to: &mut Vec<u8>, len: c_uint) -> Result<c_uint, Error> {
84 crate::ops::read(self, to, len)
85 }
86
87 #[doc(alias = "sys::ffi::playdate_file::write")]
93 #[must_use]
94 #[inline(always)]
95 pub fn write(&mut self, from: &[u8]) -> Result<c_uint, Error> { crate::ops::write(self, from) }
96
97 #[doc(alias = "sys::ffi::playdate_file::flush")]
103 #[inline(always)]
104 pub fn flush(&mut self) -> Result<c_uint, Error> { crate::ops::flush(self) }
105
106 #[doc(alias = "sys::ffi::playdate_file::tell")]
110 #[must_use]
111 #[inline(always)]
112 pub fn tell(&mut self) -> Result<c_uint, Error> { crate::ops::tell(self) }
113
114 #[doc(alias = "sys::ffi::playdate_file::seek")]
118 #[inline(always)]
119 pub fn seek(&mut self, pos: SeekFrom) -> Result<(), Error> {
120 let (whence, pos) = pos.into_parts();
121 crate::ops::seek(self, pos, whence)
122 }
123
124 #[doc(alias = "sys::ffi::playdate_file::close")]
128 #[inline(always)]
129 pub fn close(self) -> Result<(), Error> { crate::ops::close(self) }
130}
131
132impl<Api: api::Api> Drop for File<Api> {
133 fn drop(&mut self) {
134 if !self.0.is_null() {
135 let f = self.1.close();
136 let result = unsafe { f(self.0) };
137 self.0 = core::ptr::null_mut();
138
139 match Error::ok_from_code_with(result, &self.1) {
140 Ok(_) => (),
141 Err(err) => println!("Err on file-drop: {err}"),
142 }
143 }
144 }
145}