1use crate::graphics::*;
4#[cfg(feature = "alloc")]
5use alloc::boxed::Box;
6#[cfg(feature = "alloc")]
7use alloc::vec;
8
9#[cfg(feature = "alloc")]
15pub struct FileBuf {
16 pub(crate) raw: Box<[u8]>,
17}
18
19#[cfg(feature = "alloc")]
20impl FileBuf {
21 #[must_use]
23 pub fn data(&self) -> &[u8] {
24 &self.raw
25 }
26
27 #[must_use]
29 pub fn as_font(&'_ self) -> Font<'_> {
30 Font { raw: &self.raw }
31 }
32
33 #[must_use]
35 pub fn as_image(&'_ self) -> Image<'_> {
36 Image { raw: &self.raw }
37 }
38
39 #[must_use]
40 pub fn into_vec(self) -> alloc::vec::Vec<u8> {
41 self.raw.into_vec()
42 }
43}
44
45#[cfg(feature = "alloc")]
46impl From<FileBuf> for Box<[u8]> {
47 fn from(value: FileBuf) -> Self {
48 value.raw
49 }
50}
51
52#[cfg(feature = "alloc")]
53impl From<FileBuf> for alloc::vec::Vec<u8> {
54 fn from(value: FileBuf) -> Self {
55 value.into_vec()
56 }
57}
58
59#[cfg(feature = "alloc")]
60impl TryFrom<FileBuf> for alloc::string::String {
61 type Error = alloc::string::FromUtf8Error;
62
63 fn try_from(value: FileBuf) -> Result<Self, Self::Error> {
64 let v = value.into_vec();
65 alloc::string::String::from_utf8(v)
66 }
67}
68
69pub struct File<'a> {
76 pub(crate) raw: &'a [u8],
77}
78
79impl File<'_> {
80 #[must_use]
81 pub const fn data(&self) -> &[u8] {
82 self.raw
83 }
84
85 #[must_use]
86 pub const fn as_font(&'_ self) -> Font<'_> {
87 Font { raw: self.raw }
88 }
89
90 #[must_use]
91 pub const fn as_image(&'_ self) -> Image<'_> {
92 Image { raw: self.raw }
93 }
94}
95
96#[must_use]
100pub fn get_file_size(name: &str) -> usize {
101 let path_ptr = name.as_ptr();
102 let size = unsafe { bindings::get_file_size(path_ptr as u32, name.len() as u32) };
103 size as usize
104}
105
106pub fn load_file<'a>(name: &str, buf: &'a mut [u8]) -> File<'a> {
111 let path_ptr = name.as_ptr();
112 let buf_ptr = buf.as_mut_ptr();
113 unsafe {
114 bindings::load_file(
115 path_ptr as u32,
116 name.len() as u32,
117 buf_ptr as u32,
118 buf.len() as u32,
119 );
120 }
121 File { raw: buf }
122}
123
124#[cfg(feature = "alloc")]
130#[must_use]
131pub fn load_file_buf(name: &str) -> Option<FileBuf> {
132 let size = get_file_size(name);
133 if size == 0 {
134 return None;
135 }
136 let mut buf = vec![0; size];
137 load_file(name, &mut buf);
138 Some(FileBuf {
139 raw: buf.into_boxed_slice(),
140 })
141}
142
143pub fn dump_file(name: &str, buf: &[u8]) {
148 let path_ptr = name.as_ptr();
149 let buf_ptr = buf.as_ptr();
150 unsafe {
151 bindings::dump_file(
152 path_ptr as u32,
153 name.len() as u32,
154 buf_ptr as u32,
155 buf.len() as u32,
156 );
157 }
158}
159
160pub fn remove_file(name: &str) {
162 let path_ptr = name.as_ptr();
163 unsafe {
164 bindings::remove_file(path_ptr as u32, name.len() as u32);
165 }
166}
167
168pub struct Font<'a> {
173 pub(crate) raw: &'a [u8],
174}
175
176impl<'a> From<File<'a>> for Font<'a> {
177 fn from(value: File<'a>) -> Self {
178 Self { raw: value.raw }
179 }
180}
181
182#[cfg(feature = "alloc")]
183impl<'a> From<&'a FileBuf> for Font<'a> {
184 fn from(value: &'a FileBuf) -> Self {
185 Self { raw: &value.raw }
186 }
187}
188
189mod bindings {
190 #[link(wasm_import_module = "fs")]
191 extern "C" {
192 pub(crate) fn get_file_size(path_ptr: u32, path_len: u32) -> u32;
193 pub(crate) fn load_file(path_ptr: u32, path_len: u32, buf_ptr: u32, buf_len: u32) -> u32;
194 pub(crate) fn dump_file(path_ptr: u32, path_len: u32, buf_ptr: u32, buf_len: u32) -> u32;
195 pub(crate) fn remove_file(path_ptr: u32, path_len: u32);
196 }
197}