use buf::{Buf, MutBuf};
use os;
use error::MioResult;
#[deriving(Show)]
pub enum NonBlock<T> {
Ready(T),
WouldBlock
}
impl<T> NonBlock<T> {
pub fn would_block(&self) -> bool {
match *self {
WouldBlock => true,
_ => false
}
}
pub fn unwrap(self) -> T {
match self {
Ready(v) => v,
_ => panic!("would have blocked, no result to take")
}
}
}
pub trait IoHandle {
fn desc(&self) -> &os::IoDesc;
}
pub trait IoReader {
fn read(&mut self, buf: &mut MutBuf) -> MioResult<NonBlock<()>>;
}
pub trait IoWriter {
fn write(&mut self, buf: &mut Buf) -> MioResult<NonBlock<()>>;
}
pub trait IoAcceptor<T> {
fn accept(&mut self) -> MioResult<NonBlock<T>>;
}
pub fn pipe() -> MioResult<(PipeReader, PipeWriter)> {
let (rd, wr) = try!(os::pipe());
Ok((PipeReader { desc: rd }, PipeWriter { desc: wr }))
}
pub struct PipeReader {
desc: os::IoDesc
}
impl IoHandle for PipeReader {
fn desc(&self) -> &os::IoDesc {
&self.desc
}
}
pub struct PipeWriter {
desc: os::IoDesc
}
impl IoHandle for PipeWriter {
fn desc(&self) -> &os::IoDesc {
&self.desc
}
}
impl IoReader for PipeReader {
fn read(&mut self, buf: &mut MutBuf) -> MioResult<NonBlock<()>> {
read(self, buf)
}
}
impl IoWriter for PipeWriter {
fn write(&mut self, buf: &mut Buf) -> MioResult<NonBlock<()>> {
write(self, buf)
}
}
pub fn read<I: IoHandle>(io: &mut I, buf: &mut MutBuf) -> MioResult<NonBlock<()>> {
let mut first_iter = true;
while buf.has_remaining() {
match os::read(io.desc(), buf.mut_bytes()) {
Ok(cnt) => {
buf.advance(cnt);
first_iter = false;
}
Err(e) => {
if e.is_would_block() {
return Ok(WouldBlock);
}
if e.is_eof() {
if first_iter {
return Err(e);
}
return Ok(Ready(()));
}
return Err(e);
}
}
}
Ok(Ready(()))
}
pub fn write<O: IoHandle>(io: &mut O, buf: &mut Buf) -> MioResult<NonBlock<()>> {
while buf.has_remaining() {
match os::write(io.desc(), buf.bytes()) {
Ok(cnt) => buf.advance(cnt),
Err(e) => {
if e.is_would_block() {
return Ok(WouldBlock);
}
return Err(e);
}
}
}
Ok(Ready(()))
}