diff options
| author | Jeff Olson <olson.jeffery@gmail.com> | 2013-08-19 21:57:47 -0700 |
|---|---|---|
| committer | Jeff Olson <olson.jeffery@gmail.com> | 2013-08-22 16:31:57 -0700 |
| commit | f6d897d7d97c6f75126d487da196084aaafde659 (patch) | |
| tree | 33b71a8ad866a355aaad3e04b40c6f87ed4dfc21 /src/libstd/rt | |
| parent | 47f0e91689403c8472dc63e58e735f42251427ab (diff) | |
| download | rust-f6d897d7d97c6f75126d487da196084aaafde659.tar.gz rust-f6d897d7d97c6f75126d487da196084aaafde659.zip | |
std: rt::io::file::FileStream fleshed out.. needs more work.. see extended
- change all uses of Path in fn args to &P - FileStream.read assumptions were wrong (libuv file io is non-positional) - the above will mean that we "own" Seek impl info .. should probably push it in UvFileDescriptor.. - needs more tests
Diffstat (limited to 'src/libstd/rt')
| -rw-r--r-- | src/libstd/rt/io/file.rs | 109 | ||||
| -rw-r--r-- | src/libstd/rt/rtio.rs | 5 | ||||
| -rw-r--r-- | src/libstd/rt/uv/file.rs | 40 | ||||
| -rw-r--r-- | src/libstd/rt/uv/uvio.rs | 13 |
4 files changed, 127 insertions, 40 deletions
diff --git a/src/libstd/rt/io/file.rs b/src/libstd/rt/io/file.rs index 91289611659..0e972206ea7 100644 --- a/src/libstd/rt/io/file.rs +++ b/src/libstd/rt/io/file.rs @@ -12,6 +12,11 @@ use prelude::*; use super::support::PathLike; use super::{Reader, Writer, Seek}; use super::SeekStyle; +use rt::rtio::{RtioFileDescriptor, IoFactory, IoFactoryObject}; +use rt::io::{io_error, read_error, EndOfFile}; +use rt::local::Local; +use libc::{O_RDWR, O_RDONLY, O_WRONLY, S_IWUSR, S_IRUSR, + O_CREAT, O_TRUNC, O_APPEND}; /// # FIXME #7785 /// * Ugh, this is ridiculous. What is the best way to represent these options? @@ -36,29 +41,85 @@ enum FileAccess { ReadWrite } -pub struct FileStream; +pub struct FileStream { + fd: ~RtioFileDescriptor, + last_nread: int +} impl FileStream { - pub fn open<P: PathLike>(_path: &P, - _mode: FileMode, - _access: FileAccess + pub fn open<P: PathLike>(path: &P, + mode: FileMode, + access: FileAccess ) -> Option<FileStream> { - fail!() + let open_result = unsafe { + let io = Local::unsafe_borrow::<IoFactoryObject>(); + let mut flags = match mode { + Open => 0, + Create => O_CREAT, + OpenOrCreate => O_CREAT, + Append => O_APPEND, + Truncate => O_TRUNC, + CreateOrTruncate => O_TRUNC | O_CREAT + }; + flags = match access { + Read => flags | O_RDONLY, + Write => flags | O_WRONLY, + ReadWrite => flags | O_RDWR + }; + let create_mode = match mode { + Create|OpenOrCreate|CreateOrTruncate => + S_IRUSR | S_IWUSR, + _ => 0 + }; + (*io).fs_open(path, flags as int, create_mode as int) + }; + match open_result { + Ok(fd) => Some(FileStream { + fd: fd, + last_nread: -1 + }), + Err(ioerr) => { + io_error::cond.raise(ioerr); + None + } + } } } impl Reader for FileStream { - fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { - fail!() + fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + match self.fd.read(buf, 0) { + Ok(read) => { + self.last_nread = read; + match read { + 0 => None, + _ => Some(read as uint) + } + }, + Err(ioerr) => { + // EOF is indicated by returning None + if ioerr.kind != EndOfFile { + read_error::cond.raise(ioerr); + } + return None; + } + } } fn eof(&mut self) -> bool { - fail!() + self.last_nread == 0 } } impl Writer for FileStream { - fn write(&mut self, _v: &[u8]) { fail!() } + fn write(&mut self, buf: &[u8]) { + match self.fd.write(buf, 0) { + Ok(_) => (), + Err(ioerr) => { + io_error::cond.raise(ioerr); + } + } + } fn flush(&mut self) { fail!() } } @@ -69,11 +130,29 @@ impl Seek for FileStream { fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } } +fn file_test_smoke_test_impl() { + use rt::test::*; + do run_in_newsched_task { + let message = "it's alright. have a good time"; + let filename = &Path("rt_io_file_test.txt"); + { + let mut write_stream = FileStream::open(filename, Create, ReadWrite).unwrap(); + write_stream.write(message.as_bytes()); + } + { + use str; + let mut read_stream = FileStream::open(filename, Open, Read).unwrap(); + let mut read_buf = [0, .. 1028]; + let read_str = match read_stream.read(read_buf).unwrap() { + -1|0 => fail!("shouldn't happen"), + n => str::from_bytes(read_buf.slice_to(n)) + }; + assert!(read_str == message.to_owned()); + } + } +} + #[test] -#[ignore] -fn super_simple_smoke_test_lets_go_read_some_files_and_have_a_good_time() { - let message = "it's alright. have a good time"; - let filename = &Path("test.txt"); - let mut outstream = FileStream::open(filename, Create, Read).unwrap(); - outstream.write(message.as_bytes()); +fn file_test_smoke_test() { + file_test_smoke_test_impl(); } diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 1095104773d..fedffa32844 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -16,6 +16,7 @@ use rt::io::IoError; use super::io::net::ip::{IpAddr, SocketAddr}; use rt::uv::uvio; use path::Path; +use super::io::support::PathLike; // XXX: ~object doesn't work currently so these are some placeholder // types to use instead @@ -66,9 +67,9 @@ pub trait IoFactory { fn udp_bind(&mut self, addr: SocketAddr) -> Result<~RtioUdpSocketObject, IoError>; fn timer_init(&mut self) -> Result<~RtioTimerObject, IoError>; fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileDescriptor; - fn fs_open(&mut self, path: Path, flags: int, mode:int) + fn fs_open<P: PathLike>(&mut self, path: &P, flags: int, mode:int) -> Result<~RtioFileDescriptor, IoError>; - fn fs_unlink(&mut self, path: Path) -> Result<(), IoError>; + fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>; } pub trait RtioTcpListener : RtioSocket { diff --git a/src/libstd/rt/uv/file.rs b/src/libstd/rt/uv/file.rs index f3f6c325162..056250ba968 100644 --- a/src/libstd/rt/uv/file.rs +++ b/src/libstd/rt/uv/file.rs @@ -15,7 +15,7 @@ use rt::uv::{Request, NativeHandle, Loop, FsCallback, Buf, status_to_maybe_uv_error_with_loop}; use rt::uv::uvll; use rt::uv::uvll::*; -use path::Path; +use super::super::io::support::PathLike; use cast::transmute; use libc::{c_int}; use option::{None, Some, Option}; @@ -97,7 +97,7 @@ impl FileDescriptor { FileDescriptor::new(req.get_result()) } - fn open_common(loop_: Loop, path: Path, flags: int, mode: int, + fn open_common<P: PathLike>(loop_: Loop, path: &P, flags: int, mode: int, cb: Option<FsCallback>) -> int { let complete_cb_ptr = match cb { Some(_) => compl_cb, @@ -105,39 +105,44 @@ impl FileDescriptor { }; let is_sync = cb.is_none(); let req = FsRequest::new(cb); - let result = path.to_str().to_c_str().with_ref(|p| unsafe { + let result = path.path_as_str(|p| { + p.to_c_str().with_ref(|p| unsafe { uvll::fs_open(loop_.native_handle(), req.native_handle(), p, flags, mode, complete_cb_ptr) as int + }) }); if is_sync { req.cleanup_and_delete(); } result } - pub fn open(loop_: Loop, path: Path, flags: int, mode: int, + pub fn open<P: PathLike>(loop_: Loop, path: &P, flags: int, mode: int, cb: FsCallback) -> int { FileDescriptor::open_common(loop_, path, flags, mode, Some(cb)) } - pub fn open_sync(loop_: Loop, path: Path, flags: int, mode: int) -> int { + + pub fn open_sync<P: PathLike>(loop_: Loop, path: &P, flags: int, mode: int) -> int { FileDescriptor::open_common(loop_, path, flags, mode, None) } - fn unlink_common(loop_: Loop, path: Path, cb: Option<FsCallback>) -> int { + fn unlink_common<P: PathLike>(loop_: Loop, path: &P, cb: Option<FsCallback>) -> int { let complete_cb_ptr = match cb { Some(_) => compl_cb, None => 0 as *u8 }; let is_sync = cb.is_none(); let req = FsRequest::new(cb); - let result = path.to_str().to_c_str().with_ref(|p| unsafe { - uvll::fs_unlink(loop_.native_handle(), - req.native_handle(), p, complete_cb_ptr) as int + let result = path.path_as_str(|p| { + p.to_c_str().with_ref(|p| unsafe { + uvll::fs_unlink(loop_.native_handle(), + req.native_handle(), p, complete_cb_ptr) as int + }) }); if is_sync { req.cleanup_and_delete(); } result } - pub fn unlink(loop_: Loop, path: Path, cb: FsCallback) -> int { + pub fn unlink<P: PathLike>(loop_: Loop, path: &P, cb: FsCallback) -> int { FileDescriptor::unlink_common(loop_, path, Some(cb)) } - pub fn unlink_sync(loop_: Loop, path: Path) -> int { + pub fn unlink_sync<P: PathLike>(loop_: Loop, path: &P) -> int { FileDescriptor::unlink_common(loop_, path, None) } @@ -284,7 +289,8 @@ mod test { let read_mem = vec::from_elem(read_buf_len, 0u8); let read_buf = slice_to_uv_buf(read_mem); let read_buf_ptr: *Buf = &read_buf; - do FileDescriptor::open(loop_, Path(path_str), create_flags as int, mode as int) + let p = Path(path_str); + do FileDescriptor::open(loop_, &p, create_flags as int, mode as int) |req, uverr| { let loop_ = req.get_loop(); assert!(uverr.is_none()); @@ -296,7 +302,7 @@ mod test { do fd.close(loop_) |req, _| { let loop_ = req.get_loop(); assert!(uverr.is_none()); - do FileDescriptor::open(loop_, Path(path_str), read_flags as int,0) + do FileDescriptor::open(loop_, &Path(path_str), read_flags as int,0) |req, uverr| { assert!(uverr.is_none()); let loop_ = req.get_loop(); @@ -319,7 +325,7 @@ mod test { assert!(read_str == ~"hello"); do FileDescriptor(raw_fd).close(loop_) |_,uverr| { assert!(uverr.is_none()); - do FileDescriptor::unlink(loop_, Path(path_str)) + do FileDescriptor::unlink(loop_, &Path(path_str)) |_,uverr| { assert!(uverr.is_none()); }; @@ -350,7 +356,7 @@ mod test { let write_val = "hello".as_bytes().to_owned(); let write_buf = slice_to_uv_buf(write_val); // open/create - let result = FileDescriptor::open_sync(loop_, Path(path_str), + let result = FileDescriptor::open_sync(loop_, &Path(path_str), create_flags as int, mode as int); assert!(status_to_maybe_uv_error_with_loop( loop_.native_handle(), result as i32).is_none()); @@ -364,7 +370,7 @@ mod test { assert!(status_to_maybe_uv_error_with_loop( loop_.native_handle(), result as i32).is_none()); // re-open - let result = FileDescriptor::open_sync(loop_, Path(path_str), + let result = FileDescriptor::open_sync(loop_, &Path(path_str), read_flags as int,0); assert!(status_to_maybe_uv_error_with_loop( loop_.native_handle(), result as i32).is_none()); @@ -388,7 +394,7 @@ mod test { assert!(status_to_maybe_uv_error_with_loop( loop_.native_handle(), result as i32).is_none()); // unlink - let result = FileDescriptor::unlink_sync(loop_, Path(path_str)); + let result = FileDescriptor::unlink_sync(loop_, &Path(path_str)); assert!(status_to_maybe_uv_error_with_loop( loop_.native_handle(), result as i32).is_none()); } else { fail!("nread was 0.. wudn't expectin' that."); } diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index 913b19ec38f..2acf2cccfea 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -18,7 +18,6 @@ use ops::Drop; use option::*; use ptr; use str; -use path::Path; use result::*; use rt::io::IoError; use rt::io::net::ip::{SocketAddr, IpAddr}; @@ -31,6 +30,7 @@ use rt::uv::*; use rt::uv::idle::IdleWatcher; use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr}; use unstable::sync::Exclusive; +use super::super::io::support::PathLike; #[cfg(test)] use container::Container; #[cfg(test)] use unstable::run_in_bare_thread; @@ -466,7 +466,7 @@ impl IoFactory for UvIoFactory { } as ~RtioFileDescriptor } - fn fs_open(&mut self, path: Path, flags: int, mode: int) + fn fs_open<P: PathLike>(&mut self, path: &P, flags: int, mode: int) -> Result<~RtioFileDescriptor, IoError> { let loop_ = Loop {handle: self.uv_loop().native_handle()}; let result_cell = Cell::new_empty(); @@ -497,7 +497,7 @@ impl IoFactory for UvIoFactory { return result_cell.take(); } - fn fs_unlink(&mut self, path: Path) -> Result<(), IoError> { + fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> { let loop_ = Loop {handle: self.uv_loop().native_handle()}; let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell; @@ -1636,6 +1636,7 @@ fn file_test_uvio_full_simple_impl() { use str::StrSlice; // why does this have to be explicitly imported to work? // compiler was complaining about no trait for str that // does .as_bytes() .. + use path::Path; unsafe { let io = Local::unsafe_borrow::<IoFactoryObject>(); let create_flags = O_RDWR | O_CREAT; @@ -1644,18 +1645,18 @@ fn file_test_uvio_full_simple_impl() { let mode = S_IWUSR | S_IRUSR; let path = "./file_test_uvio_full.txt"; { - let mut fd = (*io).fs_open(Path(path), create_flags as int, mode as int).unwrap(); + 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); } { - let mut fd = (*io).fs_open(Path(path), ro_flags as int, mode as int).unwrap(); + 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 read_val = str::from_bytes(read_vec.slice(0, nread as uint)); assert!(read_val == write_val.to_owned()); } - (*io).fs_unlink(Path(path)); + (*io).fs_unlink(&Path(path)); } } |
