From 05c8cc70c90032d578606e811bbb1266cd8d2fcd Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 20 Aug 2013 15:38:41 -0700 Subject: std: rework file io.. support [p]read,[p]write, impl seek/tell + more tests --- src/libstd/rt/uv/uvio.rs | 111 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 32 deletions(-) (limited to 'src/libstd/rt/uv') diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index 2acf2cccfea..2a62c782d0b 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -31,6 +31,7 @@ use rt::uv::idle::IdleWatcher; use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr}; use unstable::sync::Exclusive; use super::super::io::support::PathLike; +use libc::{lseek, c_long, SEEK_CUR}; #[cfg(test)] use container::Container; #[cfg(test)] use unstable::run_in_bare_thread; @@ -458,19 +459,20 @@ impl IoFactory for UvIoFactory { Ok(~UvTimer::new(watcher, home)) } - fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileDescriptor { - ~UvFileDescriptor { + fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileStream { + ~UvFileStream { loop_: Loop{handle:self.uv_loop().native_handle()}, fd: file::FileDescriptor(fd), - close_on_drop: close_on_drop - } as ~RtioFileDescriptor + close_on_drop: close_on_drop, + } as ~RtioFileStream } fn fs_open(&mut self, path: &P, flags: int, mode: int) - -> Result<~RtioFileDescriptor, IoError> { + -> Result<~RtioFileStream, IoError> { let loop_ = Loop {handle: self.uv_loop().native_handle()}; let result_cell = Cell::new_empty(); - let result_cell_ptr: *Cell> = &result_cell; + let result_cell_ptr: *Cell> = &result_cell; let path_cell = Cell::new(path); let scheduler = Local::take::(); do scheduler.deschedule_running_task_and_then |_, task| { @@ -478,10 +480,10 @@ impl IoFactory for UvIoFactory { let path = path_cell.take(); do file::FileDescriptor::open(loop_, path, flags, mode) |req,err| { if err.is_none() { - let res = Ok(~UvFileDescriptor { + let res = Ok(~UvFileStream { loop_: loop_, fd: file::FileDescriptor(req.get_result()), - close_on_drop: true} as ~RtioFileDescriptor); + close_on_drop: true} as ~RtioFileStream); unsafe { (*result_cell_ptr).put_back(res); } let scheduler = Local::take::(); scheduler.resume_blocked_task_immediately(task_cell.take()); @@ -1056,32 +1058,14 @@ impl RtioTimer for UvTimer { } } -pub struct UvFileDescriptor { +pub struct UvFileStream { loop_: Loop, fd: file::FileDescriptor, close_on_drop: bool } -impl UvFileDescriptor { -} - -impl Drop for UvFileDescriptor { - fn drop(&self) { - if self.close_on_drop { - let scheduler = Local::take::(); - do scheduler.deschedule_running_task_and_then |_, task| { - let task_cell = Cell::new(task); - do self.fd.close(self.loop_) |_,_| { - let scheduler = Local::take::(); - scheduler.resume_blocked_task_immediately(task_cell.take()); - }; - }; - } - } -} - -impl RtioFileDescriptor for UvFileDescriptor { - fn read(&mut self, buf: &mut [u8], offset: i64) -> Result { +impl UvFileStream { + fn base_read(&mut self, buf: &mut [u8], offset: i64) -> Result { let scheduler = Local::take::(); let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; @@ -1101,7 +1085,7 @@ impl RtioFileDescriptor for UvFileDescriptor { }; result_cell.take() } - fn write(&mut self, buf: &[u8], offset: i64) -> Result<(), IoError> { + fn base_write(&mut self, buf: &[u8], offset: i64) -> Result<(), IoError> { let scheduler = Local::take::(); let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; @@ -1123,6 +1107,69 @@ impl RtioFileDescriptor for UvFileDescriptor { } } +impl Drop for UvFileStream { + fn drop(&self) { + if self.close_on_drop { + let scheduler = Local::take::(); + do scheduler.deschedule_running_task_and_then |_, task| { + let task_cell = Cell::new(task); + do self.fd.close(self.loop_) |_,_| { + let scheduler = Local::take::(); + scheduler.resume_blocked_task_immediately(task_cell.take()); + }; + }; + } + } +} + +impl RtioFileStream for UvFileStream { + fn read(&mut self, buf: &mut [u8]) -> Result { + self.base_read(buf, -1) + } + fn write(&mut self, buf: &[u8]) -> Result<(), IoError> { + self.base_write(buf, -1) + } + fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result { + self.base_read(buf, offset as i64) + } + fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> { + self.base_write(buf, offset as i64) + } + fn seek(&mut self, pos: i64, whence: i64) -> Result<(), IoError> { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + match lseek((*self.fd), pos as c_long, whence as c_int) { + -1 => { + Err(IoError { + kind: OtherIoError, + desc: "Failed to lseek.", + detail: None + }) + }, + _ => Ok(()) + } + } + } + fn tell(&self) -> Result { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + match lseek((*self.fd), 0, SEEK_CUR) { + -1 => { + Err(IoError { + kind: OtherIoError, + desc: "Failed to lseek, needed to tell().", + detail: None + }) + }, + n=> Ok(n as u64) + } + } + } + fn flush(&mut self) -> Result<(), IoError> { + Ok(()) + } +} + #[test] fn test_simple_io_no_connect() { do run_in_newsched_task { @@ -1647,12 +1694,12 @@ fn file_test_uvio_full_simple_impl() { { let mut fd = (*io).fs_open(&Path(path), create_flags as int, mode as int).unwrap(); let write_buf = write_val.as_bytes(); - fd.write(write_buf, 0); + fd.write(write_buf); } { let mut fd = (*io).fs_open(&Path(path), ro_flags as int, mode as int).unwrap(); let mut read_vec = [0, .. 1028]; - let nread = fd.read(read_vec, 0).unwrap(); + let nread = fd.read(read_vec).unwrap(); let read_val = str::from_bytes(read_vec.slice(0, nread as uint)); assert!(read_val == write_val.to_owned()); } -- cgit 1.4.1-3-g733a5