rich_sdl2_rust/file/
rw.rs1use std::{
2 ffi::CString,
3 io::{self, Seek},
4 marker::PhantomData,
5 os::raw::c_int,
6 ptr::NonNull,
7};
8
9use super::mode::OpenMode;
10use crate::{bind, Result, Sdl, SdlError};
11
12pub struct RwOps<'a> {
14 ptr: NonNull<bind::SDL_RWops>,
15 _phantom: PhantomData<&'a mut ()>,
16}
17
18impl std::fmt::Debug for RwOps<'_> {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 f.debug_struct("RwOps")
21 .field("size", &self.size())
22 .finish_non_exhaustive()
23 }
24}
25
26impl<'a> RwOps<'a> {
27 #[must_use]
33 pub unsafe fn ptr(&self) -> NonNull<bind::SDL_RWops> {
34 self.ptr
35 }
36
37 pub fn from_file(file_name: &str, mode: OpenMode) -> Result<RwOps<'static>> {
47 let cstr = CString::new(file_name).expect("file_name must not be empty");
48 let ptr = unsafe { bind::SDL_RWFromFile(cstr.as_ptr(), mode.into_raw().as_ptr()) };
49 if ptr.is_null() {
50 Err(SdlError::Others { msg: Sdl::error() })
51 } else {
52 Ok(RwOps {
53 ptr: NonNull::new(ptr).unwrap(),
54 _phantom: PhantomData,
55 })
56 }
57 }
58
59 pub fn from_mem(buf: &'a [u8]) -> Result<Self> {
65 let ptr = unsafe { bind::SDL_RWFromConstMem(buf.as_ptr().cast(), buf.len() as c_int) };
66 if ptr.is_null() {
67 Err(SdlError::Others { msg: Sdl::error() })
68 } else {
69 Ok(RwOps {
70 ptr: NonNull::new(ptr).unwrap(),
71 _phantom: PhantomData,
72 })
73 }
74 }
75
76 pub fn from_mem_mut(buf: &'a mut [u8]) -> Result<Self> {
82 let ptr = unsafe { bind::SDL_RWFromMem(buf.as_mut_ptr().cast(), buf.len() as c_int) };
83 if ptr.is_null() {
84 Err(SdlError::Others { msg: Sdl::error() })
85 } else {
86 Ok(RwOps {
87 ptr: NonNull::new(ptr).unwrap(),
88 _phantom: PhantomData,
89 })
90 }
91 }
92
93 pub fn size(&self) -> Result<usize> {
99 let ret = unsafe { bind::SDL_RWsize(self.ptr.as_ptr()) };
100 if ret < 0 {
101 Err(SdlError::Others { msg: Sdl::error() })
102 } else {
103 Ok(ret as usize)
104 }
105 }
106
107 pub fn tell(&mut self) -> io::Result<u64> {
113 self.stream_position()
114 }
115
116 pub fn read_u8(&mut self) -> u8 {
118 unsafe { bind::SDL_ReadU8(self.ptr.as_ptr()) }
119 }
120 pub fn read_be16(&mut self) -> u16 {
122 unsafe { bind::SDL_ReadBE16(self.ptr.as_ptr()) }
123 }
124 pub fn read_le16(&mut self) -> u16 {
126 unsafe { bind::SDL_ReadLE16(self.ptr.as_ptr()) }
127 }
128 pub fn read_be32(&mut self) -> u32 {
130 unsafe { bind::SDL_ReadBE32(self.ptr.as_ptr()) }
131 }
132 pub fn read_le32(&mut self) -> u32 {
134 unsafe { bind::SDL_ReadLE32(self.ptr.as_ptr()) }
135 }
136 pub fn read_be64(&mut self) -> u64 {
138 unsafe { bind::SDL_ReadBE64(self.ptr.as_ptr()) }
139 }
140 pub fn read_le64(&mut self) -> u64 {
142 unsafe { bind::SDL_ReadLE64(self.ptr.as_ptr()) }
143 }
144
145 pub fn write_u8(&mut self, value: u8) -> bool {
147 unsafe { bind::SDL_WriteU8(self.ptr.as_ptr(), value) == 1 }
148 }
149 pub fn write_be16(&mut self, value: u16) -> bool {
151 unsafe { bind::SDL_WriteBE16(self.ptr.as_ptr(), value) == 1 }
152 }
153 pub fn write_le16(&mut self, value: u16) -> bool {
155 unsafe { bind::SDL_WriteLE16(self.ptr.as_ptr(), value) == 1 }
156 }
157 pub fn write_be32(&mut self, value: u32) -> bool {
159 unsafe { bind::SDL_WriteBE32(self.ptr.as_ptr(), value) == 1 }
160 }
161 pub fn write_le32(&mut self, value: u32) -> bool {
163 unsafe { bind::SDL_WriteLE32(self.ptr.as_ptr(), value) == 1 }
164 }
165 pub fn write_be64(&mut self, value: u64) -> bool {
167 unsafe { bind::SDL_WriteBE64(self.ptr.as_ptr(), value) == 1 }
168 }
169 pub fn write_le64(&mut self, value: u64) -> bool {
171 unsafe { bind::SDL_WriteLE64(self.ptr.as_ptr(), value) == 1 }
172 }
173}
174
175impl Drop for RwOps<'_> {
176 fn drop(&mut self) {
177 let _ = unsafe { bind::SDL_RWclose(self.ptr.as_ptr()) };
178 }
179}
180
181impl io::Read for RwOps<'_> {
182 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
183 let ret = unsafe {
184 bind::SDL_RWread(
185 self.ptr.as_ptr(),
186 buf.as_mut_ptr().cast(),
187 1,
188 buf.len() as _,
189 )
190 };
191 if ret == 0 {
192 Err(io::Error::new(
193 io::ErrorKind::Other,
194 SdlError::Others { msg: Sdl::error() },
195 ))
196 } else {
197 Ok(ret as _)
198 }
199 }
200}
201
202impl io::Seek for RwOps<'_> {
203 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
204 let ret = match pos {
205 io::SeekFrom::Start(pos) => unsafe {
206 bind::SDL_RWseek(self.ptr.as_ptr(), pos as i64, 0)
207 },
208 io::SeekFrom::End(pos) => unsafe { bind::SDL_RWseek(self.ptr.as_ptr(), pos, 2) },
209 io::SeekFrom::Current(pos) => unsafe { bind::SDL_RWseek(self.ptr.as_ptr(), pos, 1) },
210 };
211 if ret < 0 {
212 Err(io::Error::new(
213 io::ErrorKind::Other,
214 SdlError::Others { msg: Sdl::error() },
215 ))
216 } else {
217 Ok(ret as u64)
218 }
219 }
220}
221
222impl io::Write for RwOps<'_> {
223 #[allow(clippy::unnecessary_cast)]
224 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
225 let written =
226 unsafe { bind::SDL_RWwrite(self.ptr.as_ptr(), buf.as_ptr().cast(), 1, buf.len() as _) }
227 as usize;
228 if written < buf.len() {
229 Err(io::Error::new(
230 io::ErrorKind::Other,
231 SdlError::Others { msg: Sdl::error() },
232 ))
233 } else {
234 Ok(written)
235 }
236 }
237
238 fn flush(&mut self) -> io::Result<()> {
239 Ok(())
240 }
241}