mirror of
https://github.com/encounter/rust-sdl2.git
synced 2026-07-10 21:18:41 -07:00
Add RWops struct implementation
This commit is contained in:
+131
-6
@@ -1,22 +1,147 @@
|
||||
use std::io;
|
||||
use std::io::IoResult;
|
||||
use get_error;
|
||||
use libc::{c_void, c_int};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub mod ll {
|
||||
use libc::{c_uchar, uint8_t, uint32_t, c_schar};
|
||||
use libc::{c_uchar, uint32_t, c_schar, FILE, c_void};
|
||||
use libc::{c_int, int64_t, size_t};
|
||||
|
||||
struct SDL_RWops_Anon {
|
||||
data: [c_uchar, ..24],
|
||||
}
|
||||
|
||||
pub type SDL_bool = c_int;
|
||||
|
||||
pub static RW_SEEK_SET: c_int = 0;
|
||||
pub static RW_SEEK_CUR: c_int = 1;
|
||||
pub static RW_SEEK_END: c_int = 2;
|
||||
|
||||
pub struct SDL_RWops {
|
||||
pub size: *uint8_t,
|
||||
pub seek: *uint8_t,
|
||||
pub read: *uint8_t,
|
||||
pub write: *uint8_t,
|
||||
pub close: *uint8_t,
|
||||
pub size: extern "C" fn(context: *SDL_RWops) -> int64_t,
|
||||
pub seek: extern "C" fn(context: *SDL_RWops, offset: int64_t, whence: c_int) -> int64_t,
|
||||
pub read: extern "C" fn(context: *SDL_RWops, ptr: *c_void,
|
||||
size: size_t, maxnum: size_t) -> size_t,
|
||||
pub write: extern "C" fn(context: *SDL_RWops, ptr: *c_void,
|
||||
size: size_t, maxnum: size_t) -> size_t,
|
||||
pub close: extern "C" fn(context: *SDL_RWops) -> c_int,
|
||||
pub _type: uint32_t,
|
||||
hidden: SDL_RWops_Anon
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn SDL_RWFromFile(file: *c_schar, mode: *c_schar) -> *SDL_RWops;
|
||||
pub fn SDL_RWFromFP(fp: *FILE, autoclose: SDL_bool) -> *SDL_RWops;
|
||||
pub fn SDL_RWFromMem(mem: *c_void, size: c_int) -> *SDL_RWops;
|
||||
pub fn SDL_RWFromConstMem(mem: *c_void, size: c_int) -> *SDL_RWops;
|
||||
|
||||
pub fn SDL_AllocRW() -> *SDL_RWops;
|
||||
pub fn SDL_FreeRW(area: *SDL_RWops);
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Eq)] #[allow(raw_pointer_deriving)]
|
||||
pub struct RWops {
|
||||
pub raw: *ll::SDL_RWops,
|
||||
pub owned: bool
|
||||
}
|
||||
|
||||
/// A structure that provides an abstract interface to stream I/O.
|
||||
impl RWops {
|
||||
pub fn from_file(path: &Path, mode: &str) -> Result<~RWops, ~str> {
|
||||
let raw = unsafe {
|
||||
ll::SDL_RWFromFile(path.to_c_str().unwrap(), mode.to_c_str().unwrap())
|
||||
};
|
||||
if raw.is_null() { Err(get_error()) }
|
||||
else { Ok(~RWops{raw: raw, owned: true}) }
|
||||
}
|
||||
|
||||
pub fn from_bytes(buf: &[u8]) -> Result<~RWops, ~str> {
|
||||
let raw = unsafe {
|
||||
ll::SDL_RWFromConstMem(buf.as_ptr() as *c_void, buf.len() as c_int)
|
||||
};
|
||||
if raw.is_null() { Err(get_error()) }
|
||||
else { Ok(~RWops{raw: raw, owned: true}) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RWops {
|
||||
fn drop(&mut self) {
|
||||
// TODO: handle close error
|
||||
unsafe {
|
||||
ll::SDL_FreeRW(self.raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reader for RWops {
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||
let out_len = buf.len() as u64;
|
||||
// FIXME: it's better to use as_mut_ptr().
|
||||
// number of objects read, or 0 at error or end of file.
|
||||
let ret = unsafe {
|
||||
((*self.raw).read)(self.raw, buf.as_ptr() as *c_void, 1, out_len)
|
||||
};
|
||||
if ret == 0 {
|
||||
Err(io::standard_error(io::EndOfFile))
|
||||
} else {
|
||||
Ok(ret as uint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for RWops {
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
let in_len = buf.len() as u64;
|
||||
let ret = unsafe {
|
||||
((*self.raw).write)(self.raw, buf.as_ptr() as *c_void, 1, in_len)
|
||||
};
|
||||
if ret == 0 {
|
||||
Err(io::standard_error(io::EndOfFile))
|
||||
} else if ret != in_len {
|
||||
// FIXME: what error should we return here?
|
||||
Err(io::standard_error(io::EndOfFile))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Seek for RWops {
|
||||
fn tell(&self) -> IoResult<u64> {
|
||||
let ret = unsafe {
|
||||
((*self.raw).seek)(self.raw, 0, ll::RW_SEEK_CUR)
|
||||
};
|
||||
if ret == -1 {
|
||||
Err(io::IoError::last_error())
|
||||
} else {
|
||||
Ok(ret as u64)
|
||||
}
|
||||
}
|
||||
|
||||
fn seek(&mut self, pos: i64, style: io::SeekStyle) -> IoResult<()> {
|
||||
// whence code is different from SeekStyle
|
||||
let whence = match style {
|
||||
io::SeekSet => ll::RW_SEEK_SET,
|
||||
io::SeekEnd => ll::RW_SEEK_END,
|
||||
io::SeekCur => ll::RW_SEEK_CUR
|
||||
};
|
||||
let ret = unsafe {
|
||||
((*self.raw).seek)(self.raw, pos, whence)
|
||||
};
|
||||
if ret == -1 {
|
||||
Err(io::IoError::last_error())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Container for RWops {
|
||||
fn len(&self) -> uint {
|
||||
unsafe {
|
||||
((*self.raw).size)(self.raw) as uint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -166,7 +166,7 @@ impl Surface {
|
||||
|
||||
pub fn from_bmp(path: &Path) -> Result<~Surface, ~str> {
|
||||
let raw = unsafe {
|
||||
ll::SDL_LoadBMP_RW(rwops::ll::SDL_RWFromFile(path.to_c_str().unwrap(), "rb".to_c_str().unwrap()), 1)
|
||||
ll::SDL_LoadBMP_RW(rwops::RWops::from_file(path, "rb").unwrap().raw, 0)
|
||||
};
|
||||
|
||||
if raw.is_null() { Err(get_error()) }
|
||||
@@ -174,9 +174,9 @@ impl Surface {
|
||||
}
|
||||
|
||||
pub fn save_bmp(&self, path: &Path) -> bool {
|
||||
unsafe {
|
||||
ll::SDL_SaveBMP_RW(self.raw, rwops::ll::SDL_RWFromFile(path.to_c_str().unwrap(), "wb".to_c_str().unwrap()), 1) == 0
|
||||
}
|
||||
unsafe {
|
||||
ll::SDL_SaveBMP_RW(self.raw, rwops::RWops::from_file(path, "rb").unwrap().raw, 0) == 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_palette(&self, palette: &pixels::Palette) -> bool {
|
||||
@@ -221,7 +221,7 @@ impl Surface {
|
||||
Err(get_error())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn set_color_mod(&self, color: pixels::Color) -> bool {
|
||||
let (r, g, b) = match color {
|
||||
pixels::RGB(r, g, b) => (r, g, b),
|
||||
|
||||
Reference in New Issue
Block a user